Python 使用lambdas的魔术方法

Python 使用lambdas的魔术方法,python,object,lambda,Python,Object,Lambda,我正在尝试使用类型动态创建对象。具体来说,我想创建一个具有len的浮点 这就是我所尝试的: _float = type('_float', (float,), {}) 另一个文件,其中是使用函数(构造函数)引用创建的实例: obj = x[1](x[0]) # `x` is a 2-length tuple: (value, function) obj.old = x[0] obj.__len__ = lambda: len(x[0]) # I'm not sure if this la

我正在尝试使用
类型
动态创建对象。具体来说,我想创建一个具有
len
的浮点

这就是我所尝试的:

_float = type('_float', (float,), {})
另一个文件,其中是使用函数(构造函数)引用创建的实例:

obj = x[1](x[0])  # `x` is a 2-length tuple: (value, function)

obj.old = x[0]
obj.__len__ = lambda: len(x[0])  # I'm not sure if this lambda should take argument 'self'

out.append(obj)  # 'out' is a list of output
这段代码在循环中,完成后,我运行以下代码(用于测试bug在哪里):

打印(输出[0]。旧版)#=>1,正确吗
打印(输出[0]。_________)#
打印(输出[0]。_len__())#1,正确(位数)
打印(len(out[0]))#类型错误:类型为“_float”的对象没有len()

基本思想是用户导入我的模块,给它一个
str
值和一个函数。然后,我的模块对象将该函数应用于
str
值,并返回结果对象。但是,它必须保持原始值,或者至少保持其
\uu len\uuu

解释了它不起作用的原因

TL;DR您正在将
\uu\len\uu
方法添加到实例dict,而不是类本身

试试这个:

_float.__len__ = lambda self: YOUR_LEN
那么这就行了:

print(len(_float(1)))
但正如评论所建议的那样,通过定义一个类来对float进行子类化,正常的方法就不那么麻烦了

编辑:

如果希望
\uuu len\uuu
方法返回
旧属性的长度,可以这样做:

_float.__len__ = lambda self: self.old
如果对没有
old
属性的对象调用
len
,则此操作可能失败

AttributeError: '_float' object has no attribute 'old'
也许这就足够了:

class _float(float):
    def __len__(self):
        return len(str(self))

不使用动态类型。

这是python 3和python 2的区别之一。这可以在Python2中使用(使用“老式”类),但在Python3中失败

例如,在python 2中,以下工作:

class test: pass # "old style" class
a = test()
a.__len__ = lambda: 10
len(a) # 10
但事实并非如此

class test(object): pass # inherit from object, "new style" class
a = test()
a.__len__ = lambda self: 10
len(a) # TypeError: object of type 'test' has no len()
而且它在Python3中不起作用,因为所有类都是“新样式”

本质上,在新样式的类中,任何使用内置重载方法(两边都有双下划线的方法)的东西都将完全绕过实例,直接转到类

只要在类上定义方法,它就可以正常工作。例如(python 3)

事实上,您甚至可以在创建实例后创建该方法

class test: pass
a = test()
a.__class__.__len__ = lambda self: 10
len(a) # 10

搜索“PythonNewStyleClasses方法查找”应该会为您提供比您所希望的更多的信息。此外,《学习Python》第五版(Oreilly,2013)的第32章和第38章深入讨论了这些差异。

为什么要动态创建它,而不是简单地子类化
float
?@DanielRoseman我认为当我调用
类型(…,(float,),{})时,我正在子类化该类型,不是吗?我对这很陌生,如果这对你来说很明显的话,对不起。是的,但有什么意义呢?为什么标准的
class\u float(float):…
,并在该类上正常定义
\uu len\uuu
方法呢?@DanielRoseman我想在我的模块中动态添加
\ulen\uuu
属性,并创建可移植的模块,这样用户就不需要定义他的自定义类(使用语句)。我还希望
\uuu len\uuuu
完全按照我的要求运行,因此如果用户自己定义它,我希望它也能重新定义。@R.O.S.S一些示例用法会很好。从描述中我看不出你是在尝试做一些真正酷的事情,还是一些非常愚蠢和过分的事情。。。您能否添加
\u float
的完整示例以及如何使用它?(并显示您所指的“可移植”/“自定义类”位)
class test: pass
test.__len__ = lambda self: 10
a = test()
len(a) # 10
class test: pass
a = test()
a.__class__.__len__ = lambda self: 10
len(a) # 10