Использование декораторов в качестве атрибутов класса вместо атрибутов экземпляра
У меня есть следующие классы.
Validator
– это декоратор, который получает класс, который определяет критерии проверки для украшенной функции. ValidateKeys
– это критерии проверки для этого примера. Node2D
– это класс, использующий критерии проверки.
class Validator(object): def __init__(self, TheValidator, *args, **kwargs): self.validator = TheValidator(*args,**kwargs) def __call__(self,f): def wrapped_f(instance, *args,**kwargs): self.TheValidator(instance, *args, **kwargs) return f(instance,*args,**kwargs) return wrapped_f class ValidateKeys(object): def __init__(self,*keysIterable): self.validkeys = keysIterable def __call__(self, instance, **kwargs): for a in kwargs: if not a in self.validkeys: raise Exception() instance.__dict__.update(kwargs) class Node2D(object): @property def coords(self): return self.__dict__ @coords.setter def coords(self,Coords): self.set_coords(**Coords) @Validator(ValidateKeys, 'x','y') def set_coords(self,**Coords): pass
Из того, что я понимаю, как написано здесь, каждый экземпляр Node2D
создает дубликат Validator
(как и любой другой класс, украшенный Validator
) и ValidateKeys
.
РЕДАКТИРОВАТЬ: ЭТО НЕПРАВИЛЬНО ! См. Ответ ниже.
Обратите внимание, что это прежде всего учебное упражнение для меня, и хотя мне было бы интересно услышать критику / предложения по улучшению моего подхода, я должен прежде всего узнать, как эффективно использовать декораторов.
Также обратите внимание, что я обычно не использовал бы капитализацию для класса декоратора, но я использую его здесь, так как это облегчает чтение на SO.
- Порядок оценки в списке python и кортежей
- Класс импорта без выполнения .py он находится внутри?
- Вызов сценариев Lua / Python в приложении для Android
- Получить список всех имен моделей NDB (имена классов) в GAE Python
- Как выйти из pdb и позволить программе продолжить?
Мое предположение было неверным.
Поскольку все написано, для каждого класса создается только один экземпляр Validator
и ValidateKeys
. Я не понимал, что строка @Validator(ValidateKeys, 'x','y')
работает только один раз (во время определения класса), а не при создании экземпляра.
Я должен был это осознать, поскольку выражения декоратора появляются на том же уровне иерархии, что и атрибуты класса , например:
class MyClass(): class_attribute = None #only one class_attribute is created @decorator #only one decorator (ie, decorated method) is created def method(): pass
Контрольная работа:
class Validator(object): def __init__(self, TheValidator, *args, **kwargs): print("New Validator Object") self.TheValidator = TheValidator(*args,**kwargs) def __call__(self,f): def wrapped_f(instance, *args,**kwargs): self.TheValidator(instance, *args, **kwargs) return f(instance,*args,**kwargs) return wrapped_f class ValidateKeys(object): def __init__(self,*keysIterable): print("New ValidateKeys Object") self.validkeys = keysIterable def __call__(self, instance, **kwargs): for a in kwargs: if not a in self.validkeys: raise Exception() instance.__dict__.update(kwargs) class Node2D(object): @property def coords(self): return self.__dict__ @coords.setter def coords(self,Coords): self.set_coords(**Coords) @Validator(ValidateKeys, 'x','y') def set_coords(self,**Coords): pass n1 = Node2D() n2 = Node2D() n1.setcoords(x=1,y=2) n1.coords
Вывод:
'New Validator Object' #<-- Seen only once when module is loaded (class defined) 'New ValidateKeys Object' #<-- Seen only once when module is loaded (class defined) '{'x': 1, 'y': 2}'
У меня нет такой проблемы, как я думал. Спасибо всем за помощь.
- Порядок базовых классов и супер () использования в множественном наследовании
- Обход изображений из поиска google с помощью python
- Частота глобальных переменных в python?
- Помощь «Установить» модуль для Python с помощью WGET
- mysql при использовании concurrent.futures
- Python: __file__ вызывающего
- ASCII Python Art # 2
- Как решить ошибку памяти в mtrand.RandomState.choice?
- Pycharm – Как получить доступ к панели «Часы»?
- Python: исключение catch внутри класса
- Python – создание списка IP-адресов с пользовательского ввода