Existe-t-il un moyen de créer une propriété en lecture seule au niveau de la classe dans Python? Par exemple, si j'ai une classe Foo
, je veux dire:Propriétés en lecture seule au niveau de la classe en Python
x = Foo.CLASS_PROPERTY
mais empêcher quiconque de dire:
Foo.CLASS_PROPERTY = y
EDIT: J'aime la simplicité de Alex Martelli's solution, mais pas le syntaxe requise. Les deux son et ~unutbu's answer s inspire la solution suivante, qui est plus à l'esprit de ce que je cherchais:
class const_value (object):
def __init__(self, value):
self.__value = value
def make_property(self):
return property(lambda cls: self.__value)
class ROType(type):
def __new__(mcl,classname,bases,classdict):
class UniqeROType (mcl):
pass
for attr, value in classdict.items():
if isinstance(value, const_value):
setattr(UniqeROType, attr, value.make_property())
classdict[attr] = value.make_property()
return type.__new__(UniqeROType,classname,bases,classdict)
class Foo(object):
__metaclass__=ROType
BAR = const_value(1)
BAZ = 2
class Bit(object):
__metaclass__=ROType
BOO = const_value(3)
BAN = 4
Maintenant, je reçois:
Foo.BAR
# 1
Foo.BAZ
# 2
Foo.BAR=2
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# AttributeError: can't set attribute
Foo.BAZ=3
#
Je préfère cette solution parce que:
- les membres se déclarent en ligne au lieu de après le fait, comme
type(X).foo = ...
- Les valeurs des membres sont définies dans le code de la classe réelle plutôt que dans le code de la métaclasse.
Il est toujours pas idéal parce que:
- Je dois régler la
__metaclass__
afin d'interpréter correctementconst_value
objets. - Les
const_value
ne se comportent pas comme les valeurs normales. Par exemple, je ne pouvais pas l'utiliser comme valeur par défaut pour un paramètre d'une méthode de la classe.
Pourquoi quelqu'un aurait-il déjà essayé de définir Foo.CLASS_PROPERTY? C'est un style typique en Python de choisir la simplicité plutôt que la planification pour empêcher une instance théorique où quelqu'un fait quelque chose de stupide. Il n'y a rien que vous puissiez faire pour empêcher les gens de faire des trucs stupides avec votre code. –
@Mike: Vous avez raison; le bon sens dirait aux gens de ne pas modifier ces propriétés. Et pourtant, de temps en temps, ils sont modifiés. C'est pourquoi j'aime bien l'épeler (plus explicitement qu'avec des majuscules). Même justification que l'utilisation de membres privés. Les interfaces explicites sont bonnes. Ne vous méprenez pas: j'aime aussi la simplicité. Je préférerais beaucoup s'il y avait une installation intégrée pour cela (comme un décorateur @classproperty ou quelque chose). Comme c'est le cas, je ne suis même pas sûr que j'utiliserais la solution ci-dessus si cela nécessite de régler le '__metaclass__' à chaque fois. Les casquettes peuvent gagner, pour l'instant. – mjumbewu
Note pour les gens du futur: Les versions modernes de Python peuvent utiliser '@ property' dans les nouvelles classes: http://docs.python.org/library/functions.html#property –