使用lambdas的魔法方法

时间:2016-01-22 10:24:00

标签: python object lambda

我尝试使用type动态创建对象。具体来说,我想创建一个具有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

此代码已循环播放,完成后,我会执行以下操作(用于测试错误的位置):

print(out[0].old)  # => 1, correct
print(out[0].__len__)  # <function bla.bla.<lambda> at: 0xblabla>
print(out[0].__len__())  # 1, correct (number of digits)
print(len(out[0]))  # TypeError: object of type '_float' has no len()

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

3 个答案:

答案 0 :(得分:1)

here

解释了它不起作用的原因

TL; DR您正在将__len__方法添加到实例dict而不是类本身。

试试这个:

_float.__len__ = lambda self: YOUR_LEN

然后这个有效:

print(len(_float(1)))

但是,正如评论建议通过定义一个类继承float而正常的方式稍微不那么苛刻。

修改

如果您希望__len__方法返回old属性的长度,可以这样做:

_float.__len__ = lambda self: self.old

如果在没有len属性

的对象上调用old,则可能会失败
AttributeError: '_float' object has no attribute 'old'

答案 1 :(得分:1)

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

例如,在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()

并且它在python 3中不起作用,因为所有类都是“新样式”。

基本上,在新的样式类中,任何使用内置重载方法的方法(双方都有双下划线的方法)都会绕过实例,然后直接进入类。

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

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

搜索“python new style classes方法查找”应该会为您提供比此更多的信息。此外,学习Python,第5版(Oreilly,2013)的第32和38章深入讨论了这些差异。

答案 2 :(得分:0)

也许这就够了:

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

不使用动态类型。