Vorrei definire il metaclass che mi consentirà di creare proprietà (cioè setter, getter) in una nuova classe sulla base degli attributi della classe.Python - metaclasse - aggiunta di proprietà
Per esempio, vorrei definire la classe:
class Person(metaclass=MetaReadOnly):
name = "Ketty"
age = 22
def __str__(self):
return ("Name: " + str(self.name) + "; age: " + str(self.age))
Ma mi piacerebbe avere qualcosa di simile:
class Person():
__name = "Ketty"
__age = 22
@property
def name(self):
return self.__name;
@name.setter
def name(self, value):
raise RuntimeError("Read only")
@property
def age(self):
return self.__age
@age.setter
def age(self, value):
raise RuntimeError("Read only")
def __str__(self):
return ("Name: " + str(self.name) + "; age: " + str(self.age))
Ecco la metaclasse ho scritto:
class MetaReadOnly(type):
def __new__(cls, clsname, bases, dct):
result_dct = {}
for key, value in dct.items():
if not key.startswith("__"):
result_dct["__" + key] = value
fget = lambda self: getattr(self, "__%s" % key)
fset = lambda self, value: setattr(self, "__" + key, value)
result_dct[key] = property(fget, fset)
else:
result_dct[key] = value
inst = super(MetaReadOnly, cls).__new__(cls, clsname, bases, result_dct)
return inst
def raiseerror(self, attribute):
raise RuntimeError("%s is read only." % attribute)
Tuttavia, non funziona correttamente.
client = Person()
print(client)
A volte ottengo:
Name: Ketty; age: Ketty
volte
:
Name: 22; age: 22
o addirittura di errore:
Traceback (most recent call last):
File "F:\Projects\TestP\src\main.py", line 38, in <module>
print(client)
File "F:\Projects\TestP\src\main.py", line 34, in __str__
return ("Name: " + str(self.name) + "; age: " + str(self.age))
File "F:\Projects\TestP\src\main.py", line 13, in <lambda>
fget = lambda self: getattr(self, "__%s" % key)
AttributeError: 'Person' object has no attribute '____qualname__'
ho trovato esempio di come si può fare altro modo (Python classes: Dynamic properties), ma lo farei piace farlo con metaclass. Hai idea di come si possa fare o è possibile?
Grazie mille :) – hakubaa