从子类获取父私有或受保护的值

Mon*_*eal 6 python oop inheritance

好吧,我有几乎相同的问题,除了一个细节:我需要获取基类的私有值。代码:

class Parent(object):
    def __init__(self):
        self.__field = 13    

class Child(Parent):
    """docstring for Child"""
    def __init__(self):
        super(Child, self).__init__()

    def ChildMethodWhichUsingParentField(self):
        return self.__field

if __name__ == '__main__':
    c = Child()
    c.ChildMethodWhichUsingParentField()
Run Code Online (Sandbox Code Playgroud)

口译输出:

Traceback (most recent call last):
  File "foo.py", line 20, in <module>
    c.ChildMethodWhichUsingParentField()
  File "foo.py", line 16, in ChildMethodWhichUsingParentField
    return self.__field
AttributeError: 'Child' object has no attribute '_Child__field'
Run Code Online (Sandbox Code Playgroud)

问题是口译员试图_Child__field在我需要时获取_Parent__field. 我可以使用 获得这个值@property,但它会阻止封装。我也可以解决这个问题,self._Parent__field但这是丑陋的,显然是糟糕的代码。还有其他方法吗?

Blc*_*ght 9

正如您在问题中所指出的,您可以通过在子类中显式使用其名称的损坏形式来访问父属性:

def ChildMethodWhichUsingParentField(self):
    return self._Parent__field
Run Code Online (Sandbox Code Playgroud)

这是对您直接问题的唯一简单答案。

然而,如果你可以控制类Parent,这将是一个非常糟糕的设计。您不应该将双下划线属性名称用于另一个类将使用的内容(实际上您可能不应该使用它,即使您不希望有任何此类使用)。使用单个下划线 (_field )。这“证明”该属性是私有的(例如,不是类的公共 API 的一部分),而不启用名称修改。这样,如果您稍后发现另一个类确实需要访问该变量,它也可以。Python 不强制执行隐私(即使使用名称修改时也不例外),因此您始终需要依赖其他表现良好的代码。

名称修饰实际上仅适用于需要避免名称冲突的情况。例如,代理对象可能对其自己的属性使用损坏的名称,以便它可以呈现一个与另一个对象的接口(可能无法提前知道)精确复制的接口。或者,mixin 类可能对其变量使用名称修饰,因为它无法确定将在(可能是许多)与其一起继承的其他类中使用哪些属性名称。如果您要将自己使用的属性添加到其他对象(而不是self)并且希望避免错误地覆盖其现有属性,那么它也很有用。

  • @Montreal:Python 开发者社区并不认为缺乏隐私执行是一个缺陷。确实,这是一个功能。如果你真的需要的话,你可以进去修改任何东西。当事情没有按照您的预期进行并且您想要将日志记录注入现有类或内省某些内容以调试奇怪的行为时,这非常有用。 (5认同)

kum*_*ums 5

这是通过添加 getter 来实现的

class Parent(object):
    def __init__(self):
        self.__field = 13

    def get_field(self):
        return self.__field

class Child(Parent):
    def ChildMethodWhichUsingParentField(self):
        return self.get_field()

c = Child()
print c.ChildMethodWhichUsingParentField()
Run Code Online (Sandbox Code Playgroud)