11

クラス属性をスーパークラスに動的に追加したいと思います。さらに、このスーパークラスから動的に継承するクラスを作成したいので、それらのサブクラスの名前はユーザー入力に依存する必要があります。

実行時に属性を追加できるスーパークラス「Unit」があります。これはすでに機能しています。

def add_attr (cls, name, value):
    setattr(cls, name, value)

class Unit(object):
    pass

class Archer(Unit):
    pass

myArcher = Archer()
add_attr(Unit, 'strength', 5)
print "Strenght ofmyarcher: " + str(myArcher.strength)
Unit.strength = 2
print "Strenght ofmyarcher: " + str(myArcher.strength)

これにより、目的の出力が得られます
。Strenght ofmyarcher:5
Strenght ofmyarcher:2

しかし、今はサブクラスArcherを事前に定義したくはありませんが、このサブクラスの呼び出し方法をユーザーに決定させたいと思います。私はこのようなことを試しました:

class Meta(type, subclassname):
    def __new__(cls, subclassname, bases, dct):
    return type.__new__(cls, subclassname, Unit, dct)

factory = Meta()    
factory.__new__("Soldier")  

しかし、運はありません。私はここで何が新しいのか本当に理解していないと思います。結果としてここに欲しいのは

class Soldier(Unit):
    pass

工場で作成されています。そして、「ナイト」という引数でファクトリを呼び出すと、ユニットのサブクラスであるクラスナイトを作成したいと思います。

何か案は?よろしくお願いします!
さようなら
-佐野

4

2 に答える 2

14

名前からクラスを作成するには、classステートメントを使用して名前を割り当てます。観察:

def meta(name):
    class cls(Unit):
        pass

    cls.__name__ = name
    return cls

今、私は自分自身を説明する必要があると思います、等々。classステートメントを使用してクラスを作成すると、動的に実行されます。これは、を呼び出すのと同じですtype()

たとえば、次の2つのスニペットは同じことを行います。

class X(object): pass
X = type("X", (object,), {})

クラスの名前(typeの最初の引数)はに割り当てられ__name__、それで基本的には終わりです(__name__それ自体が使用されるのは、おそらくデフォルトの__repr__()実装でのみです)。動的な名前でクラスを作成するには、実際にはそのようにtypeを呼び出すか、後でクラス名を変更するだけです。classただし、構文には理由があります。便利で、後で簡単に追加したり変更したりできます。たとえば、メソッドを追加したい場合は、

class X(object):
    def foo(self): print "foo"

def foo(self): print "foo"
X = type("X", (object,), {'foo':foo})

等々。したがって、クラスステートメントを使用することをお勧めします。最初からそうできることを知っていれば、おそらくそうしていたでしょう。対処typeなどはめちゃくちゃです。

type.__new__()(ちなみに、手で呼び出すのはやめましょう。type()

于 2010-03-17T11:49:08.030 に答える
7

type()組み込み関数を見てください。

knight_class = type('Knight', (Unit,), {})
  • 最初のパラメータ:新しいクラスの名前
  • 2番目のパラメーター:親クラスのタプル
  • 3番目のパラメーター:クラス属性の辞書。

しかし、あなたの場合、サブクラスが異なる動作を実装していない場合は、Unitクラスにname属性を与えるだけで十分かもしれません。

于 2010-03-17T11:46:28.910 に答える