假设我们使用的是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的点运算符有时被实现为^{
以下内容相当于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
的子类。
然后,我在Rectangle
类中重写object.__getattribute__
的尝试通常会失败
下面显示了一个类的示例,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的点运算符的方法不止一种。
一种可读、干净且一致的方法的示例是什么
通过consistent,我的意思是在源代码中使用.
时调用我们的自定义点运算符,无论该方法是否为神奇方法
我不愿意在阳光下手动输入每一种魔法方法。
我不想看到成千上万行代码,它们看起来像:
def __len__(*args, **kwargs):
return getattr(args[0], "__len__")(*args, **kwargs)
我理解__getattr__
和__getattribute__
之间的区别
覆盖__getattribute__
而不是__getattr__
是而不是当前的问题
__getattribute__
已经完成了您实际要求的操作-覆盖__getattribute__
就是处理.
运算符的所有使用所需的全部操作。(严格地说,如果__getattribute__
失败,Python将退回到__getattr__
,但只要不实现__getattr__
,就不必担心这一点。)你说你想让你的操作符被调用“只要源代码中使用了}、{}或{}中没有{}
.
”,但是len
,+
,以及你担心的所有其他事情都不要使用.
。在{大多数魔法方法查找不使用属性访问。如果您实际查找
yourobj.__len__
或yourobj.__add__
,则将通过属性访问,并且将调用__getattribute__
,但是当Python查找实现语言功能的神奇方法时,它会直接搜索对象类型的MRO。不涉及.
运算符没有办法覆盖magic方法查找。这是一个没有覆盖钩子的硬编码过程。您可以做的最接近的事情是重写单个的magic方法以委托给
__getattribute__
,但这与重写magic方法查找(或重写.
)不同,这样很容易产生无限递归错误如果您真正想做的是避免重复的单个魔术方法重写,那么可以将它们放在类装饰器或mixin中
相关问题 更多 >
编程相关推荐