0

次のようなコードがあります。

class Action(object):
    ...

class SpecificAction1(Action):
    ...

class SpecificAction2(Action):
    ...

それらはすべて同じファイルで指定されます。仕様の前に、次のような辞書を置きたいと思います。

ACTIONS = {
    "SpecificAction1": SpecificAction1,
    "SpecificAction2": SpecificAction2
}

アイデアは、他のモジュールから ACTIONS ディクショナリをインポートするだけで、この 1 つのディクショナリをアクションの 1 つの標準的な文字列表現にすることができるということです (アクションは、ネットワークや、識別子が必要な他の場所を介して送信されます)。

関数ポインターと同じ方法で、このような「クラスポインター」を実行することは可能ですか? そして、私のエディタは、辞書がクラス定義の前に宣言される前に名前が未定義であると不平を言います-これは本当ですか?

また、上記が可能であれば、クラスをインスタンス化するためにこれを行うことができますACTIONS['SpecificAction2']()か?

4

2 に答える 2

1

クラスはPythonの第一級市民です。つまり、他のオブジェクトと同じように扱うことができます。その観点からACTIONS、ファイルの最後にディクショナリを定義する必要があることを除いて、構築は完全に問題ありません (他の言語とは異なり、Python では順序が重要であるためです。それ以外の場合は ReferenceError がスローされます)。

まだまだあります。これを単純化するために、いくつかのメタプログラミングを使用できます。これを考慮してください (Python2.x、3.x では構文が少し異なります):

ACTIONS = {}

class MyMeta(type):
    def __init__(cls, name, bases, nmspc):
        super(MyMeta, cls).__init__(name, bases, nmspc)
        if name != "Action": # <--- skip base class
            ACTIONS[name] = cls

class Action(object):
    __metaclass__ = MyMeta
    ...

class SpecificAction1(Action):
    ...

class SpecificAction2(Action):
    ...

ACTIONSクラスから継承する任意のクラスを辞書に自動的に取り込みますAction(ActionクラスはMyMetaとして持っているため__metaclass__)。メタプログラミングの詳細については、こちらをご覧ください。

https://python-3-patterns-idioms-test.readthedocs.org/en/latest/Metaprogramming.html

についてはACTIONS['SpecificAction2']()、はい、クラスの新しいインスタンスを作成します。これは完全に有効なコードです。

于 2013-07-31T12:49:47.537 に答える
1

はい、できます。Python は動的言語であり、まさにそれを可能にします。ただし、ACTIONS口述から、値はクラスの定義です。それらをネットワーク経由で提供する場合は、それらを文字列として渡し、使用しますgetattr

ACTIONS = {
    "SpecificAction1": 'SpecificAction1',
    "SpecificAction2": 'SpecificAction2'
}

そして、定義を含むファイルをインポートします。

module = __import__('my_actions_module')
class_ = getattr(module,ACTIONS.get('SpecificAction1'))
instance = class_()

そしてinstance、あなたが必要とするものです。

于 2013-07-31T12:44:18.517 に答える