Python:将绑定方法更改为另一个方法

Tee*_*nge 5 python class object

我试图了解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)
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时,会生成以下输出:

1 2
3 4
Traceback (most recent call last):
  File "main.py", line 17, in <module>
    p1.draw(p1)
  File "main.py", line 10, in draw2
    print("x",self.__x, "y", self.__y)
AttributeError: 'Point' object has no attribute '__x'
Run Code Online (Sandbox Code Playgroud)

为什么我不能在更改p1.draw()之后更改它以使其指向draw2?

tim*_*geb 9

嗯,这就是你试图在Python中强制实施隐私所得到的.;)

类的身体之外,你必须参考的属性__x__y作为_Point__x_Point__y因为名字改编.

如果将两个属性更改为非损坏的名称(例如_x_y)或使用名称_Point__x_Point__yin draw2,则代码不会引发错误.

在我看来,你应该在使用受损名称之前考虑三次.写出适当的文档字符串,但不要以令人讨厌的方式限制您的类的用户.使用单个下划线名称在社区中被理解为"不要触及此".

正如您已经注意到的那样,p1.draw在您的猴子补丁后行为不同,因为draw2它不是实例的绑定方法p1,因此您需要p1显式传递作为参数.我建议您在重新分配名称之前通过利用函数的描述符协议p1来绑定实例.draw2draw

将所有内容放在一起,代码

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()
Run Code Online (Sandbox Code Playgroud)

产生输出

1 2
3 4
x 1 y 2
Run Code Online (Sandbox Code Playgroud)

where draw2.__get__(p1)产生一个行为类似的callable draw2,但自动p1作为第一个参数传递.

  • draw2 .__ get __(p1)的替代方法是使用显式类型声明:`import types``p1.draw = types.MethodType(draw2,p1)`.这显式指示实例p1现在有一个绑定方法,该方法自动将"self"作为第一个参数传递 (2认同)