我有一个扩展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扩展普通类时,这项工作是正确的。
发生了什么,以及如何列出子类实例中的属性?
发布于 2021-10-05 06:58:49
要了解为什么__dict__不能工作,请检查Ashwini Chaudhary的答复。这个答案涵盖了问题的第二部分(如何列出namedtuple属性)。
要列出namedtuple属性,有_fields和_asdict
>>> import collections as c
>>> Point = c.namedtuple("Point", ["x", "y"])
>>> p1 = Point(20, 15)
>>> print(p1._fields)
('x', 'y')
>>> print(p1._asdict())
{'x': 20, 'y': 15}
>>> class SubPoint(Point): pass
...
>>> p2 = SubPoint(20, 15)
>>> print(p2._fields)
('x', 'y')
>>> print(p2._asdict())
{'x': 20, 'y': 15}注意,_fields是在类上定义的,所以您也可以这样做:
>>> print(SubPoint._fields)
('x', 'y')显然,_asdict需要一个实例,以便它可以使用这些值。
我使用Python3.9.7作为示例,我不确定这些内容是什么时候添加的(可能是知道的人可以评论)。
发布于 2014-03-31 05:15:37
问题是__slots__仅限于在其中定义的类,因此基类将始终拥有自己的__dict__属性,除非您也在那里定义__slots__。(还请注意,__dict__属性namedtuple不是普通dict,而是@财产。)
来自文档
__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
()发布于 2014-03-31 04:43:13
在子类中声明__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欢迎有解释的回答。
https://stackoverflow.com/questions/22753711
复制相似问题