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

时间:2014-10-11 20:12:39

标签: python oop inheritance

好吧,我有几乎相同的question,除了一个细节:我需要得到基类的私有值。代码:

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()

译员输出:

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'

问题是,当我需要_Child__field时,口译员会尝试获取_Parent__field。我可以使用@property来获取此值,但它会阻止封装。我也可以用self._Parent__field来解决这个问题,但这很难看,而且代码显然很糟糕。还有其他方法吗?

2 个答案:

答案 0 :(得分:2)

正如您在问题中所述,可以通过在子类中明确使用其名称的错位形式来访问父属性:

def ChildMethodWhichUsingParentField(self):
    return self._Parent__field

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

但是,如果您可以控制Parent类,那么这将是一个非常糟糕的设计。你不应该使用双下划线属性名称作为其他类类将使用的东西(即使你不期望任何这样的使用,你也可能不应该使用它)。请改用单个下划线(_field)。这个&#34;文件&#34;该属性是私有的(例如,不是类的公共API的一部分),而不启用名称修改。这样,如果你发现晚于另一个类确实需要访问它可以的变量。 Python不会强制实施隐私(即使使用了名称修改),因此您总是需要依赖其他代码才能很好地运行。

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

答案 1 :(得分:1)

这可以通过添加一个getter

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

    def get_field(self):
        return self.__field

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


    def ChildMethodWhichUsingParentField(self):
        return self.get_field()

if __name__ == '__main__':
    c = Child()
    print c.ChildMethodWhichUsingParentField()