Obecnie zastąpić klasę __setattr__
() pod koniec klasy() metoda __init__
aby zapobiec nowe stworzenie atrybutu -Jak napisać metaclass, który uniemożliwiłby tworzenie nowych atrybutów po __init __()?
class Point(object):
def __init__(self):
self.x = 0
self.y = 0
Point.__setattr__ = self._setattr
def _setattr(self, name, value):
if not hasattr(self, name):
raise AttributeError("'" + name + "' not an attribute of Point object.")
else:
super(Point, self).__setattr__(name, value)
Czy istnieje sposób, aby uniknąć przejęcia ręcznej __setattr__
(), a to automatycznie przy pomocy metaclasses?
Najbliższy przyjechałem było -
class attr_block_meta(type):
def __new__(meta, cname, bases, dctry):
def _setattr(self, name, value):
if not hasattr(self, name):
raise AttributeError("'" + name + "' not an attribute of " + cname + " object.")
object.__setattr__(self, name, value)
dctry.update({'x': 0, 'y': 0})
cls = type.__new__(meta, cname, bases, dctry)
cls.__setattr__ = _setattr
return cls
class ImPoint(object):
__metaclass__ = attr_block_meta
Czy istnieje bardziej ogólny sposób robi to w taki sposób, APRIORI znajomość podklasy atrybutów nie jest wymagana?
Zasadniczo, jak uniknąć linii dctry.update({'x': 0, 'y': 0})
i sprawić, by działało to niezależnie od nazw atrybutów klas?
P.S. - FWIW Dokonałem już oceny opcji __slots__
i nazwano cztery i nie znalazłem ich dla moich potrzeb. Proszę nie skupiać się na uproszczonym przykładzie Points(), który wykorzystałem do zilustrowania pytania; rzeczywisty przypadek użycia dotyczy znacznie bardziej złożonej klasy.
Dlaczego? W jakich okolicznościach ktoś mógłby dodać atrybut do twojej klasy? Jako autor klasy, jak to wpłynie na Ciebie? Zgodnie z maksymą "wszyscy jesteśmy zgodnymi dorosłymi" w kraju Python; w tym przypadku oznacza to, że jeśli naruszę API klasy poprzez dodanie atrybutu, odpowiadam za wszelkie konsekwencje. Python nie jest Java ani C++. – msw
@msw - Głównie w celu wychwycenia błędów dotyczących literówek JAK NAJSZYBCIEJ. Gdybym mógł uniknąć przypadkowego wpisania przez programistów _obj.staet_, a następnie zastanawiałem się, dlaczego maszyna stanowa działa niezręcznie, to ja bym to zrobił. Zasadniczo chciałbym skrócić czas pomiędzy literami a ostateczną realizacją. –
W Pythonie naprawdę nie można używać języka do wymuszania zachowania. To jeden z powodów, dla których testy i recenzje kodu są jeszcze bardziej krytyczne w Pythonie. Powiedzmy, że złapałeś przypadek "obj.staet", który opisujesz, a co powiesz na 'ojb.state' i kiedy przestajesz. Ludzie mogą (i będą) pisać złamany kod w dowolnym języku i trudno jest je chronić przed samym sobą. Wreszcie, jesteś chroniony przed połowę problemów 'staet' już: odniesienie do obiektu' jeśli obj.staet == 5: 'rzuci NameError; przypisanie "obj.staet = 6" nie zostanie przechwycone przez Pythona. – msw