Python子类无法获取父类私有属性问题求助
问题分析与解决
你的问题出在Python的**名称改写(Name Mangling)**机制上。当类中定义以双下划线__开头的属性时,Python会自动将其重命名为_类名__属性名,目的是防止子类意外覆盖父类的私有属性。
报错原因
- 父类
Queue里的self.__queue_list会被Python悄悄改写为self._Queue__queue_list - 你在子类
SuperQueue里写Queue.__queue_list,是试图访问Queue类的类属性,而非实例属性,自然找不到 - 如果写
self.__queue_list,Python会去寻找self._SuperQueue__queue_list,但这个属性从未被初始化,所以同样报错
解决方法(三种可选)
方法1:将父类属性改为保护属性(单下划线)
把父类的__queue_list改成_queue_list,单下划线表示这是“保护属性”,子类可访问但不建议随意修改:
class QueueError(Exception): pass class Queue: def __init__(self): self._queue_list = [] # 单下划线标识保护属性 def put(self, val): self._queue_list.insert(0, val) def get(self): if len(self._queue_list) == 0: raise QueueError else: val = self._queue_list[-1] del self._queue_list[-1] return val class SuperQueue(Queue): def __init__(self): super().__init__() # 用super()调用父类初始化更简洁 def isempty(self): return len(self._queue_list) == 0
方法2:在子类中使用改写后的属性名
直接用Python改写后的名称访问父类私有属性(不推荐,破坏封装性):
class QueueError(Exception): pass class Queue: def __init__(self): self.__queue_list = [] def put(self, val): self.__queue_list.insert(0, val) def get(self): if len(self.__queue_list) == 0: raise QueueError else: val = self.__queue_list[-1] del self.__queue_list[-1] return val class SuperQueue(Queue): def __init__(self): super().__init__() def isempty(self): return len(self._Queue__queue_list) == 0 # 使用改写后的属性名
方法3:在父类中添加状态查询方法(推荐)
最符合面向对象封装原则的方式,父类提供方法暴露状态,子类无需直接访问内部属性:
class QueueError(Exception): pass class Queue: def __init__(self): self.__queue_list = [] def put(self, val): self.__queue_list.insert(0, val) def get(self): if len(self.__queue_list) == 0: raise QueueError else: val = self.__queue_list[-1] del self.__queue_list[-1] return val def is_empty(self): # 父类新增状态查询方法 return len(self.__queue_list) == 0 class SuperQueue(Queue): def __init__(self): super().__init__() def isempty(self): return self.is_empty() # 调用父类方法获取状态
修改后运行测试代码,会得到正确输出:
1 dog False Queue empty
内容的提问来源于stack exchange,提问作者Oscar Castro
相关产品推荐
相关产品推荐

