【问题标题】:python 3 Call child attribute from parent methodpython 3从父方法调用子属性
【发布时间】:2017-10-26 19:52:57
【问题描述】:

不能在父方法中调用子属性,这里是测试:

#!/usr/bin/env python3

class A():
    def getPath(self):
        return self.__path

class B(A):

    def __init__( self, name, path):
        self.__name = name
        self.__path = path

instance = B('test', '/home/test/Projects')

print(instance.getPath())

运行python测试文件$ ./test.py返回

./test.py 
Traceback (most recent call last):
  File "./test.py", line 17, in <module>
    print(instance.getPath())
  File "./test.py", line 6, in getPath
    return self.__path
AttributeError: 'B' object has no attribute '_A__path'

【问题讨论】:

    标签: python-3.x inheritance methods attributes parent


    【解决方案1】:

    你得到这个是因为你使用了一个私有属性。如果你使用非私有属性来做,它会成功。

    Python 中的私有属性旨在允许每个类拥有自己的变量私有副本,而该变量不会被子类覆盖。所以在 B 中,__path 表示 _B__path,在 A 中,__path 表示 __A_path。这正是 Python 的预期工作方式。 https://docs.python.org/3/tutorial/classes.html#tut-private

    由于希望 A 能够访问 __path,因此不应使用双下划线。相反,您可以使用单个下划线,这是一种约定,表示变量是私有的,而无需实际强制执行。

    #!/usr/bin/env python3
    
    class A():
        def getPath(self):
            return self._path
    
    class B(A):
    
        def __init__( self, name, path):
            self.__name = name
            self._path = path
    
    instance = B('test', '/home/test/Projects')
    
    print(instance.getPath())
    
    $ ./test.py
    /home/test/Projects
    

    【讨论】:

      【解决方案2】:

      除非您知道为什么需要它,否则不要使用__path_path 足以将其标记为“私人”。但是,A.getPath 不应尝试返回任何未在 A 本身中定义的内容。相反,从B.__init__ 调用A.__init__ 以确保正确完成任何A 特定的初始化:

      class A:
          def __init__(self, path):
              self._path = path
      
          def get_path(self):
              return self._path
      
      class B(A):
      
          def __init__(self, name, path):
              super().__init__(path)
              self._name = name
      
      instance = B('test', '/home/test/Projects')
      
      print(instance.get_path())
      

      既然_path 已正确隔离到A,您可以切换回__path,例如,如果您担心子类会添加自己的_path 属性.

      class A:
          def __init__(self, path):
              self.__path = path
      
          def get_path(self):
              return self.__path
      
      class B(A):
          def __init__(self, name, path):
              super().__init__(path)
              self._name = name
              self._path = "foo"
      
       instance = B('test', '/home/test/Projects')
      
       print("{}, not {}".format(instance.get_path(), instance._path))
      

      【讨论】:

      • 在某些情况下,使用 A 中未定义的成员是完全有效的。这就是“模板方法”设计模式。这个想法是基类实现了不变的部分,而子类实现了变化的部分。 en.wikipedia.org/wiki/Template_method_pattern
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-26
      相关资源
      最近更新 更多