作者:劲舞团之舞之精灵_559 | 来源:互联网 | 2022-12-02 12:51
我试图了解python中的绑定方法,并实现了以下代码:
class Point:
def __init__(self, x,y):
self.__x=x
self.__y=y
def draw(self):
print(self.__x, self.__y)
def draw2(self):
print("x",self.__x, "y", self.__y)
p1=Point(1,2)
p2=Point(3,4)
p1.draw()
p2.draw()
p1.draw=draw2
p1.draw(p1)
当我运行此代码时,会生成以下输出:
1 2
3 4
Traceback (most recent call last):
File "main.py", line 17, in
p1.draw(p1)
File "main.py", line 10, in draw2
print("x",self.__x, "y", self.__y)
AttributeError: 'Point' object has no attribute '__x'
为什么我不能在更改p1.draw()之后更改它以使其指向draw2?
1> timgeb..:
嗯,这就是你试图在Python中强制实施隐私所得到的.;)
类的身体之外,你必须参考的属性__x
和__y
作为_Point__x
和_Point__y
因为名字改编.
如果将两个属性更改为非损坏的名称(例如_x
和_y
)或使用名称_Point__x
和_Point__y
in draw2
,则代码不会引发错误.
在我看来,你应该在使用受损名称之前考虑三次.写出适当的文档字符串,但不要以令人讨厌的方式限制您的类的用户.使用单个下划线名称在社区中被理解为"不要触及此".
正如您已经注意到的那样,p1.draw
在您的猴子补丁后行为不同,因为draw2
它不是实例的绑定方法p1
,因此您需要p1
显式传递作为参数.我建议您在重新分配名称之前通过利用函数的描述符协议p1
来绑定实例.draw2
draw
将所有内容放在一起,代码
class Point:
def __init__(self, x,y):
self._x=x
self._y=y
def draw(self):
print(self._x, self._y)
def draw2(self):
print("x",self._x, "y", self._y)
p1 = Point(1,2)
p2 = Point(3,4)
p1.draw()
p2.draw()
p1.draw = draw2.__get__(p1)
p1.draw()
产生输出
1 2
3 4
x 1 y 2
where draw2.__get__(p1)
产生一个行为类似的callable draw2
,但自动p1
作为第一个参数传递.
draw2 .__ get __(p1)的替代方法是使用显式类型声明:`import types``p1.draw = types.MethodType(draw2,p1)`.这显式指示实例p1现在有一个绑定方法,该方法自动将"self"作为第一个参数传递