2017-05-11 23 views
0

からクラスへの未解決の参照は、だから私はこのコードを持って:パイソン:静的変数

class MyClass: 

    ACTIONS = { 
     "ACTION_A": MyClass.__a, 
     "ACTION_B": MyClass.__b 
    } 

    @staticmethod 
    def do(constant): 
     ACTIONS[constant]() 

    @staticmethod 
    def __a(): 
     print("A") 

    @staticmethod 
    def __b(): 
     print("B") 

私は静的辞書にプライベート__a__b機能をマップしようとしているので、私はできますよメソッドを使用して関数を実行するdo

このコードを実行しようとすると、私はエラーを取得:「未解決の参照を 『MyClassの』行動辞書の各行に。

これはどのように正しく動作するかについての考え方はありますか?

+0

'static'は、Javaで同じキーワードは異なる何かを意味します。クラス単位のデータの管理には使用しないでください。それには 'classmethod'sを使います。 –

+0

そして、 'MyClass'は' ACTIONS'マッピングが作成されたときにまだ定義されていません。その名前は、 'class'ステートメントが完了した後*に設定されます。 –

+0

最後に、(フレームワークのように)どんな名前が衝突するかもしれないかについてサブクラスが心配するべきではない基本クラスを構築していない限り、 '__name'スタイル属性を使用しないでください。 Java風のプライバシーモデルはありません。これらの属性は外部の呼び出し元からはアクセスできません。彼らがすることは、属性に異なる名前空間を与えることだけです。 –

答えて

5

最初にクラスを使用するべきではありません。あなたがしているのは、名前空間を作成することだけです。そのためのモジュールを使用してください。パッケージに新しいモジュールを作成し、その中で、すべての機能を置く:私は単一下線名を使用

def _a(): 
    print("A") 

def _b(): 
    print("B") 


ACTIONS = { 
    'ACTION_A': _a, 
    'ACTION_B': _b, 
} 

def do(constant): 
    ACTIONS[constant]() 

注意。 Pythonは、クラス内で二重アンダースコア名を使用して、クラスごとの名前空間を追加します。 MyClass.__aMyClass._MyClass__aになり、サブクラスとの衝突を避けることができます(スーパークラスの暗黙のうちに名前を自由に再利用できます)。Pythonではプライバシーモデルはありません。

あなたが_a_b関数を登録するデコレータを使用することができます。

def do(constant): 
    ACTIONS[constant]() 

ACTIONS = {} 

def action(name): 
    def decorator(f): 
     ACTIONS[name] = f 
     return f 

@action('ACTION_A') 
def _a(): 
    print("A") 

@action('ACTION_B') 
def _b() 
    print("B") 

あなたが見る特定のエラーが全体class文が完了するまで設定されていないMyClass名によるものです。あなたはその辞書その後を設定する必要があると思います:doは、クラスメソッドであることを

class MyClass: 
    @classmethod 
    def do(cls, constant): 
     cls.ACTIONS[constant]() 

    @staticmethod 
    def _a(): 
     print("A") 

    @staticmethod 
    def _b(): 
     print("B") 

MyClass.ACTIONS = { 
    'ACTION_A': MyClass._a, 
    'ACTION_B': MyClass._b, 
} 

注意を、あなただけの世界としてACTIONSにアクセスすることはできません、あなたは、私が上記使用されるようにMyClass.ACTIONSか、のいずれかを使用する必要がありますクラスメソッドはclsのオブジェクトを参照します。

あなたが代わりに名前を使用することにより class文の後 ACTIONSを設定し、 def doクラスメソッドを作成する必要が周りに仕事ができる

:Pythonで

class MyClass: 
    ACTIONS = { 
     'ACTION_A': '_a', 
     'ACTION_B': '_b', 
    } 

    @classmethod 
    def do(cls, constant): 
     getattr(cls, cls.ACTIONS[constant])() 

    @staticmethod 
    def _a(): 
     print("A") 

    @staticmethod 
    def _b(): 
     print("B") 
+0

これは本当に面白いです、私は貴重なPythonの概念をいくつか学びました。あなたの洞察に感謝します。 – Strinnityk