假设我们正在使用python 3.x
或更新,而不是python 2.x
与许多语言一样,Python 有一个点运算符:
# Create a new instance of the Rectangle class
robby = Rectangle(3, 10)
# INVOKE THE DOT OPERATOR
x = robby.length
Python 的点运算符有时被实现为__getattribute__
.
以下等价于x = robby.length
:
x = Rectangle.__getattribute__(robby, "length")
但是,点运算符并不总是实现为__getattribute__
.
Python 有“魔术方法”魔术方法是名称以两个下划线字符开头和结尾的任何方法
。是魔术方法的一个例子。
__len__()
您可以通过执行以下代码来获取大多数 python 魔术方法的列表:
print("\n".join(filter(lambda s: s.startswith("__"), dir(int))))
输出是:
__abs__
__add__
__and__
__bool__
__ceil__
__class__
__delattr__
__dir__
__divmod__
__doc__
__eq__
__float__
[... truncated / abridged ...]
__rtruediv__
__rxor__
__setattr__
__sizeof__
__str__
__sub__
__subclasshook__
__truediv__
__trunc__
__xor__
假设我们编写了一个名为 的类Rectangle
,它的子类object
。
然后我尝试object.__getattribute__
在类内部覆盖Rectangle
,通常会失败。
下面显示了一个类的示例,其中 python 有时会忽略覆盖的点运算符:
class Klass:
def __getattribute__(self, attr_name):
return print
obj = Klass()
obj.append() # WORKS FINE. `obj.append == print`
obj.delete() # WORKS FINE. `obj.delete == print`
obj.length # WORKS FINE
obj.x # WORKS FINE
# None of the following work, because they
# invoke magic methods.
# The following line is similar to:
# x = Klass.__len__(obj)
len(obj)
# obj + 5
# is similar to:
# x = Klass.__add__(obj, 5)
x = obj + 5
# The following line is similair to:
# x = Klass.__radd__(obj, 2)
x = 2 + obj
有不止一种方法可以覆盖 python 的点运算符。
什么是一种可读、干净和一致的方法的例子?
一致,我的意思是我们的自定义点运算符在源代码中使用时被调用,.
无论该方法是否是魔术方法。
我不愿意在阳光下手动输入每一个魔法方法。
我不想看到成千上万行代码,如下所示:
def __len__(*args, **kwargs):
return getattr(args[0], "__len__")(*args, **kwargs)
__getattr__
我理解和__getattribute__
Overriding__getattribute__
而不是__getattr__
之间的区别不是手头的问题。