我尝试使用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__
。
答案 0 :(得分:1)
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))
不使用动态类型。