【发布时间】:2021-04-09 05:13:54
【问题描述】:
假设我们使用的是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 的子类。
然后我尝试在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 的点运算符。
什么是可读、干净且一致的一种方法示例?
一致,我的意思是,只要在源代码中使用.,我们的自定义点运算符就会被调用,无论该方法是否是魔术方法.
我不愿意在阳光下手动输入每一个魔法方法。
我不想看到成千上万行代码看起来像:
def __len__(*args, **kwargs):
return getattr(args[0], "__len__")(*args, **kwargs)
我了解__getattr__ 和__getattribute__ 之间的区别
覆盖__getattribute__ 而不是__getattr__ 是不是当前的问题。
【问题讨论】:
标签: python python-3.x operator-overloading getattribute dot-operator