包括常见的 属性 装饰器
Including common property decorators
我正在寻找一个 shorthand 来为 类 添加常见的 属性 装饰器。
class Animal:
def __init__(self):
self._attributes = {}
class Dog(Animal):
@property
def color(self):
return super()._attributes.get('color', None)
@color.setter
def color(self, value):
if value is not None:
super()._attributes['color'] = value
else:
super()._attributes.pop('color', None)
class Cat(Animal):
@property
def color(self):
return super()._attributes.get('color', None)
@color.setter
def color(self, value):
if value is not None:
super()._attributes['color'] = value
else:
super()._attributes.pop('color', None)
class InvisibleMan(Animal):
pass
我正在寻找最简单的方法来“打包”颜色 属性,这样我就可以将它分配给狗和猫,而不是 InvisibleMan。像这样的东西(尽管实际上会有 ~8 个这样的属性和 ~15 个这样的 类)
class Dog(Animal):
def __init__(self):
super().__init__()
includeColorProperty(self)
你有关于选项。
首先,多重继承:
# this is the best way to do things if lots of stuff is invisible
class HasColor:
# getter and setter go here
class Dog(Animal,HasColor):
...
或
# This is probably the best one way to do things, if not many things are invisible
class Invisible:
@property
def color(self):
raise AttributeError("very meaningful message")
class InvisibleMan(Invisible,Animal): # THE ORDER HERE MATTERS!!
etc
选项 2 将覆盖隐形人中的 getter 和 setter:
class Dog(Animal):
...
class InvisibleMan(Animal):
@property
def color(self):
raise AttributeError("very meaningful message")
奖金选项:
如果你想在一个实例上打开和关闭隐形,那么你想做其他事情。我不确定你是否想要这个但是:
class Animal:
cloaking_on = False
@property
def color(self):
if self.cloaking_on:
raise AttributeError(etc)
etc
然后你就可以有办法打开和关闭隐形,让所有的猫默认不可见。
您是否考虑过描述符而不是装饰器?
简而言之,描述符使您可以对属性存储进行细粒度控制。 (事实上,property
装饰器在幕后构建了一个描述符!)这里有一些 Python docs 可能会有帮助。
无论如何,坚持你的模式,操纵 _attributes
的描述符看起来像这样:
class Color:
def __get__(self, obj, objtype=None):
return obj._attributes.get('color')
def __set__(self, obj, value):
if value is None:
obj._attributes.pop('color', None)
else:
obj._attributes['color'] = value
其中 obj
是对 Dog
实例等的引用
(请注意 __get__
和 __set__
方法分别匹配您的 getter 和 setter。)
然后,像这样将描述符插入您的 类:
class Animal:
def __init__(self):
self._attributes = {}
class Dog(Animal):
color = Color()
class Cat(Animal):
color = Color()
class InvisibleMan(Animal):
pass
您可以在这个例子中看到您正在寻找的行为被保留:实例保持它们自己的 _attributes
,并且 InvisibleMan
没有 color
:
>>> d1, d2 = Dog(), Dog()
>>> d1.color = 'blue'
>>> d1.color, d2.color
('blue', None)
>>>
>>>
>>> x = InvisibleMan()
>>> x.color
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'InvisibleMan' object has no attribute 'color'
就我个人而言,当涉及许多属性时,我也发现这更容易阅读,正如您提到的那样,在您的情况下是正确的。想知道给定类型有哪些属性?它们列在顶部,不足为奇。
我正在寻找一个 shorthand 来为 类 添加常见的 属性 装饰器。
class Animal:
def __init__(self):
self._attributes = {}
class Dog(Animal):
@property
def color(self):
return super()._attributes.get('color', None)
@color.setter
def color(self, value):
if value is not None:
super()._attributes['color'] = value
else:
super()._attributes.pop('color', None)
class Cat(Animal):
@property
def color(self):
return super()._attributes.get('color', None)
@color.setter
def color(self, value):
if value is not None:
super()._attributes['color'] = value
else:
super()._attributes.pop('color', None)
class InvisibleMan(Animal):
pass
我正在寻找最简单的方法来“打包”颜色 属性,这样我就可以将它分配给狗和猫,而不是 InvisibleMan。像这样的东西(尽管实际上会有 ~8 个这样的属性和 ~15 个这样的 类)
class Dog(Animal):
def __init__(self):
super().__init__()
includeColorProperty(self)
你有关于选项。
首先,多重继承:
# this is the best way to do things if lots of stuff is invisible
class HasColor:
# getter and setter go here
class Dog(Animal,HasColor):
...
或
# This is probably the best one way to do things, if not many things are invisible
class Invisible:
@property
def color(self):
raise AttributeError("very meaningful message")
class InvisibleMan(Invisible,Animal): # THE ORDER HERE MATTERS!!
etc
选项 2 将覆盖隐形人中的 getter 和 setter:
class Dog(Animal):
...
class InvisibleMan(Animal):
@property
def color(self):
raise AttributeError("very meaningful message")
奖金选项:
如果你想在一个实例上打开和关闭隐形,那么你想做其他事情。我不确定你是否想要这个但是:
class Animal:
cloaking_on = False
@property
def color(self):
if self.cloaking_on:
raise AttributeError(etc)
etc
然后你就可以有办法打开和关闭隐形,让所有的猫默认不可见。
您是否考虑过描述符而不是装饰器?
简而言之,描述符使您可以对属性存储进行细粒度控制。 (事实上,property
装饰器在幕后构建了一个描述符!)这里有一些 Python docs 可能会有帮助。
无论如何,坚持你的模式,操纵 _attributes
的描述符看起来像这样:
class Color:
def __get__(self, obj, objtype=None):
return obj._attributes.get('color')
def __set__(self, obj, value):
if value is None:
obj._attributes.pop('color', None)
else:
obj._attributes['color'] = value
其中 obj
是对 Dog
实例等的引用
(请注意 __get__
和 __set__
方法分别匹配您的 getter 和 setter。)
然后,像这样将描述符插入您的 类:
class Animal:
def __init__(self):
self._attributes = {}
class Dog(Animal):
color = Color()
class Cat(Animal):
color = Color()
class InvisibleMan(Animal):
pass
您可以在这个例子中看到您正在寻找的行为被保留:实例保持它们自己的 _attributes
,并且 InvisibleMan
没有 color
:
>>> d1, d2 = Dog(), Dog()
>>> d1.color = 'blue'
>>> d1.color, d2.color
('blue', None)
>>>
>>>
>>> x = InvisibleMan()
>>> x.color
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'InvisibleMan' object has no attribute 'color'
就我个人而言,当涉及许多属性时,我也发现这更容易阅读,正如您提到的那样,在您的情况下是正确的。想知道给定类型有哪些属性?它们列在顶部,不足为奇。