我们如何始终覆盖/重载python';s点运算符,`uuuu getAttribute`?

我们如何始终覆盖/重载python';s点运算符,`uuuu getAttribute`?,python,python-3.x,operator-overloading,getattribute,dot-operator,Python,Python 3.x,Operator Overloading,Getattribute,Dot Operator,假设我们使用的是Python3.x或更高版本,而不是Python2.x 与许多语言一样,Python也有一个点运算符: #创建矩形类的新实例 robby=矩形(3,10) #调用点运算符 x=robby.length Python的点运算符有时被实现为\uu getattribute\uuu 以下内容相当于x=robby.length: x=Rectangle.\uuuuuu getattribute\uuuuuuuu(robby,“长度”) 但是,点运算符不是始终实现为\uuu getat

假设我们使用的是
Python3.x
或更高版本,而不是
Python2.x

与许多语言一样,Python也有一个点运算符:

#创建矩形类的新实例
robby=矩形(3,10)
#调用点运算符
x=robby.length
Python的点运算符有时被实现为
\uu getattribute\uuu

以下内容相当于
x=robby.length

x=Rectangle.\uuuuuu getattribute\uuuuuuuu(robby,“长度”)
但是,点运算符不是始终实现为
\uuu getattribute\uuu

Python有“神奇的方法”
魔术方法是名称以两个下划线字符开头和结尾的任何方法。
\uuu len\uuu()
是一个神奇方法的例子

通过执行以下代码,您可以获得大多数python神奇方法的列表:

print(“\n”).join(filter(lambda s:s.startswith(“\uuu”)、dir(int)))
输出为:

\u abs__
__加__
__及__
__布尔__
__细胞__
__阶级__
__德拉特__
__迪尔__
__迪夫莫德__
__医生__
__情商__
__浮动__
[…截断/删节…]
__鲁迪夫__
__rxor__
__赛特特__
__sizeof__
__str__
__潜艇__
__子类钩__
__特鲁迪夫__
__特鲁克__
__异或__
假设我们编写了一个名为
Rectangle
的类,它是
对象的子类

然后,我尝试重写
对象。
矩形
类内部的\uuuu getattribute\uuuu
通常会失败

下面显示了一个类的示例,python有时会忽略重写的点运算符:

类Klass:
def uu getattribute uu(self,attr_name):
返回打印
obj=Klass()
obj.append()#工作正常`obj.append==打印`
obj.delete()#工作正常`obj.delete==打印`
obj.length#工作正常
obj.x工作正常
#没有以下工作,因为它们
#调用神奇的方法。
#以下行类似于:
#x=Klass.\uuuu len\uuj(obj)
len(obj)
#obj+5
#类似于:
#x=Klass.\uuuuuuuuuuuuuuuuuuuj(对象5)
x=obj+5
#下一行类似于:
#x=Klass.\uuuu radd\uuuj(obj,2)
x=2+obj
重写python的点运算符的方法不止一种。
一种可读、干净且一致的方法的示例是什么

通过一致,我的意思是,只要源代码中使用
,我们的自定义点运算符就会被调用,无论该方法是否是魔术方法

我不愿意在阳光下手动输入每一种魔法方法。
我不想看到成千上万行代码,它们看起来像:

def_uuulen_uuuu(*args,**kwargs):
返回getattr(args[0],“_ulen___;”)(*args,**kwargs)
我理解
\uuuu getattr\uuuu
\uuuu getattribute\uuuuu

之间的区别
重写
\uuuu getattribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>而非
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>不是当前的问题。

\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。(严格地说,如果
\uuuuu getattribute\uuuuu
失败,Python将退回到
\uuuu getattr\uuuuuu
,但只要不实现
\uu getattr\uuuuu
,您就不必担心这一点)


你说你想让操作符“在源代码中使用
时”被调用,但是
len
+
,以及你担心的所有其他事情都不要使用
。在
len(obj)
obj+5
2+obj
中没有

大多数魔法方法查找不使用属性访问。如果您实际查找
yourobj.\uuuu len\uuuuu
yourobj.\uuuu add\uuuuu
,这将通过属性访问,并且将调用
\uu getattribute\uuuuuu
,但当Python查找实现语言功能的神奇方法时,它会直接搜索对象类型的MRO。
操作员不参与

没有办法覆盖magic方法查找。这是一个没有覆盖钩子的硬编码过程。您可以做的最接近的事情是重写单个的magic方法以委托给
\uuuu getattribute\uuuu
,但这与重写magic方法查找(或重写
)不同,这样很容易产生无限递归错误


如果您真正想做的是避免重复的单个魔术方法重写,那么您可以将它们放入类装饰器或mixin中。

\uuuuuuGetAttribute\uuuuuuu
已经完成了您真正要求的操作-重写
\uuuuuGetAttribute\uuuuu
是处理
操作符的所有使用所需的全部操作。(严格地说,如果
\uuuuu getattribute\uuuuu
失败,Python将退回到
\uuuu getattr\uuuuuu
,但只要不实现
\uu getattr\uuuuu
,您就不必担心这一点)


你说你想让操作符“在源代码中使用
时”被调用,但是
len
+
,以及你担心的所有其他事情都不要使用
。在
len(obj)
obj+5
2+obj
中没有

大多数魔法方法查找不使用属性访问。如果您实际查找
yourobj.\uuuu len\uuuuu
yourobj.\uuuu add\uuuuu
,这将通过属性访问,并且将调用
\uu getattribute\uuuuuu
,但当Python查找实现语言功能的神奇方法时,它会直接搜索对象类型的MRO。
操作员不参与

没有