Мне интересно, есть ли в 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"]
для доступа к компонентам.
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)
Технически, он удовлетворяет всем требованиям вопроса, но я искренне надеюсь, что никто никогда не использует его (я определенно не буду).