6

を拡張する小さなクラスがありますが、そのインスタンス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バニラ クラスを拡張すると、これが正しく機能することに注意してください。

サブクラス インスタンスの属性を一覧表示するにはどうすればよいですか?

4

4 に答える 4

4

問題は、__slots__それが定義されているクラスにのみ限定されているため、そこでも定義しない限り、基本クラスには常に独自の__dict__属性__slots__があります。(また、__dict__属性 ofnamedtupleは通常の dict ではなく@propertyであることに注意してください。)

ドキュメントから:

宣言のアクションは、__slots__それが定義されているクラスに限定されます。その結果、サブクラス__dict__も定義しない限り、サブクラスには a が含まれます__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-31T05:15:37.300 に答える
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

解説つきの回答大歓迎です。

于 2014-03-31T04:43:13.090 に答える