Je me demande si Python a quelque chose comme la fonctionnalité des classes anonymes de C#. Pour clarifier, voici un exemple d'extrait C# :
var foo = new { x = 1, y = 2 };
var bar = new { y = 2, x = 1 };
foo.Equals(bar); // "true"
En Python, j'imaginerais quelque chose comme ceci :
foo = record(x = 1, y = 2)
bar = record(y = 2, x = 1)
foo == bar # true
L'exigence spécifique est de pouvoir créer un objet avec des champs spécifiés dans un contexte d'expression (par exemple, utilisable dans des lambdas et d'autres endroits où les déclarations ne sont pas autorisées), sans déclarations externes supplémentaires, et de pouvoir accéder à des composants individuels par leur nom via la syntaxe normale d'accès aux membres. foo.bar
. L'objet créé doit également mettre en œuvre la comparaison structurelle par les noms des composants (et non par position, comme le font les tuples).
En particulier : les tuples ne le sont pas parce que leurs composants ne sont pas nommés ; les classes ne le sont pas parce qu'elles nécessitent une déclaration ; les dicts ne le sont pas parce qu'elles ont des effets indésirables sur la qualité de l'environnement. foo["bar"]
pour accéder aux composants.
namedtuple Ce n'est pas le cas, car il faut toujours un nom même si vous définissez le type en ligne, et la comparaison est basée sur la position et non sur le nom. En particulier :
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
Je sais comment écrire une telle chose en Python si nécessaire. Mais j'aimerais savoir s'il y a quelque chose de ce genre dans la bibliothèque standard de Python, ou dans toute autre bibliothèque tierce populaire.
[EDIT]
Juste pour le plaisir, voici une solution à une seule expression qui combine deux réponses très instructives de Ken et alanlcode, produisant une égalité structurelle sans aucune déclaration extérieure supplémentaire :
type("", (), { \
"__init__": (lambda self, **kwargs: self.__dict__.update(kwargs)), \
"__eq__": (lambda self, other: self.__dict__ == other.__dict__) } \
)(x = 1, y = 2)
Techniquement, il répond à toutes les exigences de la question, mais j'espère sincèrement que personne ne l'utilisera jamais (je ne le ferai certainement pas).
2 votes
On dirait que les dictionnaires devraient faire l'affaire. Je trouve que c'est mieux de trouver la façon de faire en python que d'intégrer un autre langage dans python. BTW -- si vous n'aimez pas la méthode d'accès au dictionnaire, foo["bar"] une alternative est d'utiliser la méthode get : foo.get("bar")
1 votes
Étant donné qu'il est trivialement possible de l'implémenter en Python si nécessaire, je ne vois pas de raison particulière de ne pas le faire, et je ne considère absolument pas que c'est "adapter un autre langage à Python". D'autant plus que cela semble assez proche de l'existant
namedtuple
dans l'intention.2 votes
Je trouve bizarre de poser la question de savoir si la langue X a la caractéristique de la langue Y, et d'exiger ensuite que tout soit exactement pareil. Les langues ne sont pas exactement les mêmes. Python n'a pas de fonctions anonymes, mais ils ont des dictionnaires, et ils fonctionnent tout aussi bien. Oui, la syntaxe d'accès est différente. La belle affaire.
3 votes
Je ne demande pas que les fonctionnalités soient exactement les mêmes - si c'était le cas, je demanderais aussi un typage statique et l'immuabilité ;) Je demande simplement une syntaxe que je considère comme plus naturelle et plus pratique.
0 votes
Au début, j'avais tendance à créer des objets afin de pouvoir y coller des données pour accéder aux attributs. Vous vous habituerez vite aux dicts.
0 votes
Voir aussi : stackoverflow.com/q/13897205/680372
0 votes
Tu n'as pas besoin de ces barres obliques inversées. En Python, une ligne n'est pas terminée tant que les parenthèses ne sont pas toutes fermées.