Bien que je n'ai jamais eu besoin de cela, cela m'a juste frappé que créer un objet immuable en Python pouvait être légèrement délicat. Vous ne pouvez pas simplement remplacer __setattr__
, car vous ne pouvez même pas définir d'attributs dans le __init__
. Sous-classer un tuple est une astuce qui fonctionne:
class Immutable(tuple):
def __new__(cls, a, b):
return tuple.__new__(cls, (a, b))
@property
def a(self):
return self[0]
@property
def b(self):
return self[1]
def __str__(self):
return "<Immutable {0}, {1}>".format(self.a, self.b)
def __setattr__(self, *ignored):
raise NotImplementedError
def __delattr__(self, *ignored):
raise NotImplementedError
Mais alors vous avez accès à a
et les b
variables à travers self[0]
et self[1]
, ce qui est gênant.
Est-ce possible en Pure Python? Sinon, comment le ferais-je avec une extension C?
(Les réponses qui ne fonctionnent que dans Python 3 sont acceptables).
Mise à jour:
Donc, sous-classer le tuple est le moyen de le faire en Pure Python, qui fonctionne bien sauf pour la possibilité supplémentaire d'accéder aux données par [0]
, [1]
etc. Donc, pour compléter cette question, tout ce qui manque est comment le faire "correctement" en C, ce qui Je suppose que ce serait assez simple, en n'implémentant aucun geititem
ou setattribute
, etc. Mais au lieu de le faire moi-même, j'offre une prime pour cela, parce que je suis paresseux. :)
la source
.a
et.b
? C'est pour cela que les propriétés semblent exister après tout.NotImplemented
est uniquement conçue comme une valeur de retour pour les comparaisons riches. Une valeur de retour pour__setatt__()
est de toute façon plutôt inutile, car vous ne la verrez généralement pas du tout. Le code commeimmutable.x = 42
ne fera rien en silence. Vous devriez lever un à laTypeError
place.NotImplementedError
, maisTypeError
c'est ce qu'un tuple déclenche si vous essayez de le modifier.