7

SQLAlchemyのさまざまなプロジェクト(およびPygameのいくつかのプロジェクト)からの無数のPythonクラスがあり、最近、それらの多くにパターンがあることに気づきました。それらのコンストラクターは常に次のようになりました。

class Foo(Base):
    def __init__(self, first, last, email, mi=""):
        self.first = first
        self.last = last
        self.email = email
        self.mi = mi

...これにより、コンストラクターが行ったのは、位置引数のセットをまったく同じ名前のデータメンバーのセットに転送することだけで、計算やその他の関数呼び出しは一切実行しませんでした。

この繰り返しは不要であり、変更時に人為的ミスが発生しやすいように思われます。

これは私にここでの質問につながります:__init__(self, ...)できればCPythonバイトコードをいじったり、テンプレート/マクロを使用してソースファイル自体を変更したりせずに、そのような関数を自動的に生成することは可能ですか?

4

4 に答える 4

2

おそらくメタクラスでこれを行うことができます。オーバーライドするメタクラスの例を次に示します。Python__init__()クラス デコレータ

もちろん、フィールド/引数の名前を何らかの方法で指定する必要があります。または、必要に応じて、名前付き引数を使用する必要があります。これを行う1つの方法は次のとおりです。

# This is the mataclass-defined __init__
def auto_init(self, *args, **kwargs):
    for arg_val, arg_name in zip(args, self.init_args):
        setattr(self, arg_name, arg_val)

    # This would allow the user to explicitly specify field values with named arguments
    self.__dict__.update(kwargs)

class MetaBase(type):
    def __new__(cls, name, bases, attrs):
        attrs['__init__'] = auto_init
        return super(MetaBase, cls).__new__(cls, name, bases, attrs)

class Base(object):
    __metaclass__ = MetaBase

# No need to define __init__
class Foo(Base):
    init_args = ['first', 'last', 'email', 'mi']
于 2011-05-09T01:05:51.923 に答える
2

python> = 3.7の場合、これを処理する適切な方法は次のdataclassesとおりです。

__init__()このモジュールは、やなどの生成された特別なメソッド__repr__()をユーザー定義クラスに自動的に追加するためのデコレータと関数を提供します。もともとはPEP557で説明されていました。

于 2020-07-02T14:58:21.983 に答える
1

あなたはこのようなことをすることができます:

class Foo(Base):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

これを行う際の問題の1つは、すべてのインスタンスが同じメンバーを持つという保証がないことです。もう1つの問題は、すべてのコンストラクターをキーワード引数で呼び出す必要があることです。

于 2011-05-09T01:18:46.737 に答える
0

namedtupleをチェックしてください:

>>> from collections import namedtuple
>>> Foo = namedtuple("Foo", "first last email mi")
>>> f = Foo("Alfred", "Neumann", "aen@madmagazine.com", "E")
>>> f
Foo(first='Alfred', last='Neumann', email='aen@madmagazinecom', mi='E')
于 2011-05-09T04:41:18.763 に答える