6

クラスに関する情報をクラス(静的)変数として保存したいと思います。しかし、これらがどのように初期化されるのか理解できません。これが基本的な、ばかげた例です:

class A(object):
    clsVar = 'a'
    @classmethod
    def clsMeth(cls):
        print 'changing clsVar'
        cls.clsVar = 'b'
    A.clsMeth()
# prints 'changing clsVar'

print A.clsVar    # prints 'a'
A.clsVar = 'b'
print A.clsVar    # prints 'b'

関数が呼び出されたので(printステートメントが機能したため)、クラス変数が変更されたままにならなかったのはなぜですか?クラス定義の完了後にメタクラスを使用したくない場合は、メタクラスを使用する必要がありますか?

[具体的には、私clsMethはデコレータになり、クラス変数をそのように装飾されたすべての関数のリストにしたいです。これはそれを達成するための正しい方法ではないと思うので、先に進みましたが、それでも興味があります。]

編集:多くの人が指摘しているように、上記のコードは実行されません。A.clsMeth()の呼び出しが以前のバージョンのを参照して実行するIPythonセッションで実行していましたA。これが通訳言語を使うことのリスクだと思います。私はこのようなもので行くことになりました:

outsideDict = {}
def outsideDec(func):
    outsideDict[func.__name__] = func

class A(object):
    @outsideDec
    def someMethod(self):
        print 'ID %s' % id(self)

    def otherMethod(self):
        print 'other'

print outsideDict
one, two = A(), A()
outsideDict['someMethod'](one)
outsideDict['someMethod'](two)

おそらくこれは別の質問になるはずoutsideDecですが、実行されたときに、引数がどのクラスのメンバーであるかを判断する方法はありますか?または、Pythonでこのようなイントロスペクションを行うためのより良い方法はありますか?私はここでコースを逸脱していることを認識しているので、以下の回答を受け入れてさらに調査を行います。みんな、ありがとう!

4

1 に答える 1

5

A.clsMeth()その時点では存在しないため、 の定義内のへの呼び出しAは実行されAません。

>>> class A(object):
...     clsVar = 'a'
...     @classmethod
...     def clsMeth(cls):
...         print 'changing clsVar'
...         cls.clsVar = 'b'
...     A.clsMeth()
... 
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<stdin>", line 7, in A
NameError: name 'A' is not defined

コードがA以前に定義されていた場合 (たとえば、REPL でテストしていた場合) は機能しているように見えたかもしれませんが、への呼び出しA.clsMethは古いクラスで呼び出され、新しいクラスによってシャドウされます。

ただし、その呼び出しを定義の後に置くことで、必要な結果を得ることができます。

>>> class A(object):
...     clsVar = 'a'
...     @classmethod
...     def clsMeth(cls):
...         print 'changing clsVar'
...         cls.clsVar = 'b'
...
>>> A.clsMeth()
changing clsVar
>>> A.clsVar
'b'

もちろん、fabianhrj が指摘したように、コンストラクターに配置することもできますが、インスタンスを作成するまで呼び出されません。

于 2011-12-14T18:44:58.697 に答える