是否可以修改len()的行为?

Zac*_*tes 12 python python-3.x

我知道创建自定义__repr____add__方法(等等),以修改运算符和函数的行为.是否有方法覆盖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.
Run Code Online (Sandbox Code Playgroud)

这可以len用列表来完成吗?通常,它看起来像这样:

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

foo = [1, 2, 3]
print(len(foo))    # 3
Run Code Online (Sandbox Code Playgroud)

如果我想让搜索类型超出计数范围怎么办?像这样:

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
Run Code Online (Sandbox Code Playgroud)

有没有办法在list子类中执行此操作?

Mar*_*ers 19

是的,实施__len__方法:

def __len__(self):
    return 42
Run Code Online (Sandbox Code Playgroud)

演示:

>>> class Foo(object):
...     def __len__(self):
...         return 42
... 
>>> len(Foo())
42
Run Code Online (Sandbox Code Playgroud)

从文档:

被称为实现内置功能len().应该返回对象的长度,整数>=0.此外,在布尔上下文中,未定义__bool__()方法且其__len__()方法返回零的对象被视为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
Run Code Online (Sandbox Code Playgroud)


wim*_*wim 7

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

>>> class Thing:
...     def __len__(self):
...         return 123
...     
>>> len(Thing())
123
Run Code Online (Sandbox Code Playgroud)

一个学究者可能会提到你没有修改你的行为len(),你正在修改你班级的行为. len它总是做同样的事情,包括检查__len__参数的属性.


Jam*_*lls 5

请记住:Python是一种动态和Duck类型的语言.

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

class MyCollection(object):

    def __len__(self):
        return 1234
Run Code Online (Sandbox Code Playgroud)

例:

>>> obj = MyCollection()
>>> len(obj)
1234
Run Code Online (Sandbox Code Playgroud)

如果它不像它有长度那样; KABOOM!

class Foo(object):

    def __repr___(self):
        return "<Foo>"
Run Code Online (Sandbox Code Playgroud)

例:

>>> 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()
Run Code Online (Sandbox Code Playgroud)

键入:

Python使用duck typing并且有类型的对象但是无类型的变量名.在编译时不检查类型约束; 相反,对象上的操作可能会失败,表示给定的对象不是合适的类型.尽管是动态类型的,但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'
Run Code Online (Sandbox Code Playgroud)