Python: разрешать устанавливать только атрибуты, которые имеют декоратор @property

#python #getter-setter

#python #установщик получения

Вопрос:

 class MyClass():
   def __init__(self):
      self.attribute_1 = "foo"
      self.attribute_2 = "bar"
 
   @property
   def attribute_1(self):
     return self._attribute_1

   @attribute_1.setter
   def attribute_1(self,s):
     self._attribute_1 = s

   @property
   def attribute_2(self):
     return self._attribute_2

   @attribute_2.setter
   def attribute_2(self,s):
     self._attribute_2 = s

>>> ob = MyClass()
>>> ob.attribute_1 = 'fizz' #Ok
>>> ob.atribute_1 = 'buzz' #want to throw an exception because this has no setter or @property def
  

Я бы хотел, чтобы мой класс жаловался, если мы попытаемся установить атрибут, который не был оформлен property и setter. Я пробовал использовать слоты, но не могу заставить его работать с декоратором свойств. 'attribute' in __slots__ conflicts with class variable

Есть мысли?

Комментарии:

1. __slots__ было бы ["_attribute_1", "_attribute_2"] так, поскольку это 2 переменные, которые вы используете в качестве фактических переменных экземпляра (вы не включаете методы или свойства в слоты), это не работает для вас?

2. @tadhg Вот и все!

3. Это своего рода противоположность Python. Почему вы хотите это сделать?

4. Потому что я сумасшедший.

5. Кроме того, эти свойства абсолютно бессмысленны, и вы должны просто использовать обычные атрибуты

Ответ №1:

__slots__ должны содержать все переменные экземпляра, в вашем случае это _attribute_1 и _attribute_2 (те, у которых символы подчеркивания используются внутри), поэтому просто сделайте это:

 class MyClass():
   __slots__ = ["_attribute_1", "_attribute_2"]
   pass # rest of implementation
  

обратите внимание, что если ваше свойство просто перенаправляет напрямую, вы могли бы также просто поместить общедоступные переменные в слоты и иметь свойства только для полей, которые нуждаются в дополнительной проверке или другой логике. наличие слотов фактически является свойством на самом деле:

 >>> MyClass._attribute_1
<member '_attribute_1' of 'MyClass' objects>