namedtuple子类的列表属性
问题描述:
我有一个小类扩展了namedtuple
,但其实例的__dict__
属性总是返回空。namedtuple子类的列表属性
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
延伸香草类时请注意此功能正确。
发生了什么,以及如何列出我的子类实例中的属性?
答
问题是__slots__
仅限于它定义的类,所以基类将始终拥有自己的__dict__
属性,除非您还定义了__slots__
。 (同时也注意,namedtuple
的__dict__
属性是不正常的字典而是@property)
从docs:
一个
__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__)
输出:
{}
--------------------
inside A
()
答
在子类中声明__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
欢迎有解释的答案。