Мне интересно, есть ли у Python что-то вроде функции анонимных классов С#. Чтобы прояснить, здесь пример фрагмента С#:
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
Конкретным требованием является создание объекта с указанными полями в контексте выражения (например, использование в lambdas и других местах, где утверждения не допускаются), без дополнительных внешних объявлений и возможности доступа к отдельным компонентам по имени через синтаксис доступа к нормальному члену foo.bar
. Созданный объект также должен реализовывать структурное сравнение по именам компонентов (не по положению, как это делают кортежи).
В частности: кортежи - это не потому, что их компоненты не называются; классы - это не потому, что они требуют объявления; dicts не потому, что они имеют нежелательный синтаксис foo["bar"]
для доступа к компонентам.
namedtuple не так, потому что он все еще требует имени, даже если вы определяете тип inline, а сравнение - а не на основе имени. В частности:
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]
Просто ради этого, здесь одно выражение выражение, которое объединяет два очень информативных ответов Кена и alanlcode, что дает структурное равенство без каких-либо дополнительных внешних заявлений:
type("", (), { \
"__init__": (lambda self, **kwargs: self.__dict__.update(kwargs)), \
"__eq__": (lambda self, other: self.__dict__ == other.__dict__) } \
)(x = 1, y = 2)
Технически, он удовлетворяет всем требованиям вопроса, но я искренне надеюсь, что никто никогда его не использует (я определенно не буду).