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 

欢迎有解释的答案。