我有一个扩展namedtuple
的小类,但其实例的__dict__
属性始终为空。
Point = namedtuple('Point', 'x y')
p1 = Point(20, 15)
print(p1, p1.__dict__)
# Point(x=20, y=15) OrderedDict([('x', 20), ('y', 15)]) <--- ok
class SubPoint(Point): pass
p2 = SubPoint(20, 15)
print(p2, p2.__dict__)
# SubPoint(x=20, y=15) {} <--- why is it empty?
p2
具有属性,但其__dict__
为空。它们与dir()
一起正确列出,这很奇怪。当SubPoint
扩展一个vanilla类时,请注意这项工作正确。
发生了什么,我如何在子类实例中列出属性?
答案 0 :(得分:4)
问题是__slots__
仅限于它所定义的类,因此基类将始终具有自己的__dict__
属性,除非您在那里定义__slots__
。 (另请注意,__dict__
的{{1}}属性不是普通字典,而是@property。)
来自docs:
namedtuple
声明的操作仅限于其所在的类 被定义为。因此,子类将具有__slots__
,除非它们 还定义__dict__
(必须包含任何其他名称 时隙)。
因此,当您在子类中定义__slots__
时,它无法在该类中查找属性__slots__
,因此转移到找到__dict__
属性的基类。
一个简单的演示:
__dict__
<强>输出:强>
class A:
__slots__= ('a', 'b')
@property
def __dict__(self):
print ('inside A')
return self.__slots__
class B(A):
pass
print(B().__dict__)
print ('-'*20)
class B(A):
__slots__ = ()
print(B().__dict__)
答案 1 :(得分:0)
在子类中声明__slots__ = ()
修复了问题,但原因尚不清楚。据我所知__slots__
不应该以这种微妙的方式改变代码的行为,所以这不是一个完整的答案。
Point = namedtuple('Point', 'x y')
p1 = Point(20, 15)
print(p1, p1.__dict__)
# Point(x=20, y=15) OrderedDict([('x', 20), ('y', 15)]) <--- ok
class SubPoint(Point):
__slots__ = ()
p2 = SubPoint(20, 15)
print(p2, p2.__dict__)
# SubPoint(x=20, y=15) OrderedDict([('x', 20), ('y', 15)]) <--- fixed
欢迎给出解释答案。
答案 2 :(得分:0)
list(A.__annotations__.keys())