2015-05-27 79 views
12

我知道创建一个自定义__repr____add__方法(以此类推),以修改操作符和函数的行为。 len有没有方法覆盖?是否可以修改len()的行为?

例如:

class Foo: 
    def __repr__(self): 
     return "A wild Foo Class in its natural habitat." 

foo = Foo() 

print(foo)   # A wild Foo Class in its natural habitat. 
print(repr(foo)) # A wild Foo Class in its natural habitat. 

会这样做了len,与列表?通常情况下,它应该是这样的:

foo = [] 
print(len(foo)) # 0 

foo = [1, 2, 3] 
print(len(foo)) # 3 

如果我要离开搜索类型出计的?就像这样:

class Bar(list): 
    pass 

foo = [Bar(), 1, ''] 
print(len(foo)) # 3 

count = 0 
for item in foo: 
    if not isinstance(item, Bar): 
     count += 1 

print(count)  # 2 

有没有办法从list子内做到这一点?

+3

你已经有很好的答案,但如果你想了解更多关于魔术方法我可以建议[A指南Python的魔术方法(HTTP:// WWW。 rafekettler.com/magicmethods.html);) – swenzel

+0

这会派上用场!感谢分享。 @swenzel –

+0

你有一个列表子类,而不是一个列表超类。 – wim

回答

19

是,贯彻__len__ method

def __len__(self): 
    return 42 

演示:

>>> class Foo(object): 
...  def __len__(self): 
...   return 42 
... 
>>> len(Foo()) 
42 

从文档:

调用来实现的内置功能len()。应该返回对象的长度,一个整数>= 0.另外,没有定义__bool__()方法且其方法返回0的对象在布尔上下文中被认为是false。

对于您的具体情况:

>>> class Bar(list): 
...  def __len__(self): 
...   return sum(1 for ob in self if not isinstance(ob, Bar)) 
... 
>>> len(Bar([1, 2, 3])) 
3 
>>> len(Bar([1, 2, 3, Bar()])) 
3 
+0

'将自己的ob(不是isinstance(ob,Bar)')稍微清洁一点? – TigerhawkT3

+0

@ TigerhawkT3:在这一点上,你必须解释Python的布尔类型是int的一个子类,“True”的整数值为1,“False”的值为0.它并不总是值得少一点代码当你必须每一次解释。 –

+0

非常真实;我没有这样想过。 – TigerhawkT3

7

是的,正如你已经发现,则可以覆盖实现__repr__魔术方法repr()函数调用的行为,您可以指定行为通过实施(意外惊喜)一len()函数调用然后__len__魔法:

>>> class Thing: 
...  def __len__(self): 
...   return 123 
...  
>>> len(Thing()) 
123 

一个学究可能会提到,你没有修改len()的行为,你正在修改你的类的行为。 len只是做它一直做的同样的事情,其中​​包括检查参数__len__属性。

3

您只需在课程中添加__len__方法即可。

class Test: 
    def __len__(self): 
     return 2 

a=Test() 
len(a) # --> 2 
5

记住:Python是一个动态和Duck Typed语言。

如果它的行为像可能有一个长度的东西;

class MyCollection(object): 

    def __len__(self): 
     return 1234 

实施例:

>>> obj = MyCollection() 
>>> len(obj) 
1234 

如果它不像它具有一长度;KABOOM!

class Foo(object): 

    def __repr___(self): 
     return "<Foo>" 

实施例:

>>> try: 
...  obj = Foo() 
...  len(obj) 
... except: 
...  raise 
... 
Traceback (most recent call last): 
    File "<stdin>", line 3, in <module> 
TypeError: object of type 'Foo' has no len() 

Typing

Python使用鸭打字和已键入对象,但无类型变量 名称。类型约束在编译时不检查;而对对象的操作可能会失败,表示给定的对象是 不是合适的类型。尽管是动态输入,但Python是强类型的,它禁止未定义好的操作(例如, 示例向字符串添加数字),而不是默默尝试 来理解它们。

例子:

>>> x = 1234 
>>> s = "1234" 
>>> x + s 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unsupported operand type(s) for +: 'int' and 'str'