1. ホーム
  2. python

[解決済み] Pythonに匿名クラスはありますか?

2023-06-04 06:22:54

質問

PythonにC#の匿名クラス機能のようなものがあるのかどうか気になります。明確にするために、ここにC#のサンプルスニペットがあります。

var foo = new { x = 1, y = 2 };
var bar = new { y = 2, x = 1 };
foo.Equals(bar); // "true"

Pythonでいうと、こんな感じでしょうか。

foo = record(x = 1, y = 2)
bar = record(y = 2, x = 1)
foo == bar  # true

具体的な要件は、指定したフィールドを持つオブジェクトを式コンテキストで作成できること(例えば、ラムダやステートメントが許されない他の場所で使用可能)、追加の外部宣言がないこと、通常のメンバーアクセス構文で名前によって個々のコンポーネントにアクセスすることができることです。 foo.bar . 作成されたオブジェクトは構造比較も実装する必要があります コンポーネント名による (を実装しなければなりません(タプルのように位置による比較ではありません)。

特に、タプルはそのコンポーネントが名前付きでないため、そうではありません。クラスは宣言が必要なため、そうではありません。ディクツは望ましくない foo["bar"] の構文で構成要素にアクセスできるからです。

名前付きタプル はそうではありません。なぜなら、インラインで型を定義してもまだ名前が必要であり、比較は名前ベースではなく位置ベースで行われるからです。特に

 def foo(): return namedtuple("Foo", "x y")(x = 1, y = 2)
 def bar(): return namedtuple("Foo", "y x")(x = 1, y = 2)
 foo() == bar()   # False because fields are compared in order, and not by name
                  # True would be desired instead

必要であれば、Pythonでそのようなものを書く方法は知っています。しかし、Pythonの標準ライブラリや、人気のあるサードパーティライブラリにそのようなものがあるかどうか知りたいです。

[EDIT】をご覧ください。]

念のため、Ken と alanlcode による 2 つの非常に有益な回答を組み合わせた単一式の解決策を紹介します。

type("", (), { \
    "__init__": (lambda self, **kwargs: self.__dict__.update(kwargs)), \
    "__eq__": (lambda self, other: self.__dict__ == other.__dict__) } \
)(x = 1, y = 2)

技術的には質問の要件をすべて満たしていますが、私は誰もこれを使わないことを心から願っています(私は絶対に使いません)。

どのように解決するのですか?

Pythonicな方法としては dict :

>>> foo = dict(x=1, y=2)
>>> bar = dict(y=2, x=1)
>>> foo == bar
True

をしなければならないことを除けば、すべての要求を満たしています。 foo['x'] の代わりに foo.x .

それが問題なら、簡単にこんなクラスを定義すればいい。

class Bunch(object):
    def __init__(self, **kwds):
        self.__dict__.update(kwds)

    def __eq__(self, other):
        return self.__dict__ == other.__dict__

または、素敵で短いもの

class Bunch(dict):
    __getattr__, __setattr__ = dict.get, dict.__setitem__

(ただし、この2番目のものは、アレックスがコメントで指摘しているように問題があることに注意してください!)