代码之家  ›  专栏  ›  技术社区  ›  DarkKnight

Python类继承-属性混淆

  •  0
  • DarkKnight  · 技术社区  · 5 年前

    在我看来,当程序员必须处理其他人开发的类时,Python中似乎存在固有的困难,因为他/她有必要的文档(如何构建它,有哪些函数等),但没有实现的细节。当然,当事情开始出错时,可以检查源代码,但所说的类可能是完全健壮的,直到有人想将其子类化。

    考虑一下这个琐碎的例子:-

    class Base():
        def __init__(self):
            self._n = 99
    
        @property
        def n(self):
            return self._n
    
        @n.setter
        def n(self, n):
            self._n = n
    
        def func(self):
            print(self.n)
    

    这里的关键是Base有一个函数,在某种程度上依赖于属性_n。

    我现在决定要开发一个类,该类将Base子类化。所以,我写下:-

    class Myclass(Base):
        def __init__(self, n):
            super().__init__()
            self.n = n
    

    现在我有麻烦了,因为我刚刚 zapped 我的超类中的一个属性,并且可能完全破坏了它的功能。

    针对这一潜在问题,是否有任何发展模式或任何其他形式的防御措施?

    0 回复  |  直到 5 年前
        1
  •  1
  •   kaya3 Amit Bera    5 年前

    您可以通过使用来避免“切换”超类的属性 name mangling 用于“私有”*属性。名称以两个下划线**开头的属性的名称将自动损坏,这样它们就不会与超类中声明的名称发生冲突。

    class A:
        def __init__(self):
            self.__x = 1
        def get_A_x(self):
            return self.__x
    
    class B(A):
        def __init__(self):
            super().__init__()
            self.__x = 2
        def get_B_x(self):
            return self.__x
    
    obj = B()
    print(obj.get_A_x(), obj.get_B_x())
    # prints "1 2"
    

    在最好的情况下,为了保护自己的“私有”属性,超类总是被编写为使用名称篡改。如果没有,那么至少您可以确保子类中名称被篡改的属性不会与它们发生冲突;仍然存在这样的风险 平民的 子类的属性可能与超类的未知“私有”属性冲突。在这种情况下,你能做的最好的事情(除了在他们的问题跟踪器上打开一个问题)是通过检查 __dict__ 属性,然后避免与这些名称发生冲突。

    *当然,在Python中,没有属性 真正地 私有的即使名称被篡改的属性也可以从声明它们的类外部访问,如果它们是通过其被篡改的名称访问的话。
    **不包括像这样的“灌篮方法” __init__ ,或以两个或多个下划线结尾的任何其他名称。