列出namedtuple子类的属性

时间:2014-03-31 04:34:47

标签: python attributes subclass python-3.3 namedtuple

我有一个扩展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类时,请注意这项工作正确。

发生了什么,我如何在子类实例中列出属性?

3 个答案:

答案 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())