- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试掌握(开始;))以了解如何在 Python 3 上正确使用装饰器和描述符。我想出了一个想法,我正在尝试弄清楚如何对其进行编码。
我希望能够创建一个用某些“函数”B或“类”B装饰的类A,它允许我创建 A 的实例,将 A 的属性声明为某种类型的组件并为 A 赋值 __init__
魔术函数。例如:
组件化是某些“函数B”或“类B”,它允许我声明一个类Vector。我声明 x 和 y 是一个组件( float ),如下所示:
@componentized
class Vector:
x = component(float)
y = component(float)
def __init__ (self, x, y):
self.x = x
self.y = y
我的想法是能够做到这一点:
v = Vector(1,2)
v.x #returns 1
但主要目标是我想对每个标记的组件( float )属性执行此操作:
v.xy #returns a tuple (1,2)
v.xy = (3,4) #assigns to x the value 3 and y the value 4
我的想法是创建一个装饰器@componentized来覆盖__getattr__
和__setattr__
魔术方法。类似这样:
def componentized(cls):
class Wrapper(object):
def __init__(self, *args):
self.wrapped = cls(*args)
def __getattr__(self, name):
print("Getting :", name)
if(len(name) == 1):
return getattr(self.wrapped, name)
t = []
for x in name:
t.append(getattr(self.wrapped, x))
return tuple(t)
@componentized
class Vector(object):
def __init__(self, x, y):
self.x = x
self.y = y
这确实有效,但我认为我不太明白发生了什么。因为当我尝试进行分配并覆盖 __setattr__ 魔术方法时,即使我实例化该类,它也会被调用。在以下示例中两次:
vector = Vector(1,2)
vector.x = 1
我怎样才能实现这种行为?
提前致谢!如果需要更多信息,请随时询问!
编辑:
按照@Diego的回答,我设法做到了这一点:
def componentized(cls):
class wrappedClass(object):
def __init__(self, *args, **kwargs):
t = cls(*args,**kwargs)
self.wrappedInstance = t
def __getattr__(self, item):
if(len(item) == 1):
return self.wrappedInstance.__getattribute__(item)
else:
return tuple(self.wrappedInstance.__getattribute__(char) for char in item)
def __setattr__(self, attributeName, value):
if isinstance(value, tuple):
for char, val in zip(attributeName, value):
self.wrappedInstance.__setattr__(char, val)
elif isinstance(value, int): #EMPHASIS HERE
for char in attributeName:
self.wrappedInstance.__setattr__(char, value)
else:
object.__setattr__(self, attributeName, value)
return wrappedClass
并且有一个像这样的Vector类:
@componentized
class Vector:
def __init__ (self, x, y):
self.x = x
self.y = y
这有点像我想要的,但我仍然不知道如何实现:
x = component(float)
y = component(float)
在Vector类中以某种方式订阅float类型的x和y,所以当我执行#EMPHASIS LINE(在我硬编码特定类型的行中)我可以检查代码中是否有人正在为实例的 x 和/或 y 分配值Vector 的类型是我定义的:
x = component(float)
所以我尝试了这个(组件(描述符)类):
class component(object):
def __init__(self, t, initval=None):
self.val = initval
self.type = t
def __get__(self, obj, objtype):
return self.val
def __set__(self, obj, val):
self.val = val
像描述符一样使用组件,但我无法设法采取解决方法来处理该类型。我尝试创建一个数组来保存 val 和 type,但后来不知道如何从装饰器 __setattr__ 方法中获取它。
你能指出我正确的方向吗?
PS:希望你们理解我想要做什么并帮助我。提前致谢
好吧,使用@Diego的答案(我将接受)和一些解决方法来满足我的个人需求,我成功做到了:
def componentized(cls):
class wrappedClass(object):
def __init__(self, *args):
self.wrappedInstance = cls(*args)
def __getattr__(self, name):
#Checking if we only request for a single char named value
#and return the value using getattr() for the wrappedInstance instance
#If not, then we return a tuple getting every wrappedInstance attribute
if(len(name) == 1):
return getattr(self.wrappedInstance, name)
else:
return tuple(getattr(self.wrappedInstance, char) for char in name)
def __setattr__(self, attributeName, value):
try:
#We check if there is not an instance created on the wrappedClass __dict__
#Meaning we are initializing the class
if len(self.__dict__) == 0:
self.__dict__[attributeName] = value
elif isinstance(value, tuple): # We get a Tuple assign
self.__checkMultipleAssign(attributeName)
for char, val in zip(attributeName, value):
setattr(self.wrappedInstance, char, val)
else:
#We get a value assign to every component
self.__checkMultipleAssign(attributeName)
for char in attributeName:
setattr(self.wrappedInstance, char, value)
except Exception as e:
print(e)
def __checkMultipleAssign(self, attributeName):
#With this we avoid assigning multiple values to the same property like this
# instance.xx = (2,3) => Exception
for i in range(0,len(attributeName)):
for j in range(i+1,len(attributeName)):
if attributeName[i] == attributeName[j]:
raise Exception("Multiple component assignment not allowed")
return wrappedClass
class component(object):
def __init__(self, t):
self.type = t #We store the type
self.value = None #We set an initial value to None
def __get__(self, obj, objtype):
return self.value #Return the value
def __set__(self, obj, value):
try:
#We check whether the type of the component is diferent to the assigned value type and raise an exeption
if self.type != type(value):
raise Exception("Type \"{}\" do not match \"{}\".\n\t--Assignation never happened".format(type(value), self.type))
except Exception as e:
print(e)
else:
#If the type match we set the value
self.value = value
(代码注释不言自明)
通过这个设计,我可以实现我想要的(如上所述)感谢大家的帮助。
最佳答案
我认为有一个最简单的方法来实现这种行为:重载 __getattr__
和__setattr__
功能。
class Vector:
...
def __getattr__(self, item):
return tuple(object.__getattribute__(self, char) for char in item)
__getattr__
仅当访问属性的“正常”方式失败时才调用函数,如 Python documentation 中所述。 。所以,当python找不到vector.xy
时,__getattr__
方法被调用,我们返回每个值的元组(即 x 和 y)。
我们使用object.__getattribute__
以避免无限递归。
def __setattr__(self, key, value):
if isinstance(value, tuple) and len(key) == len(value):
for char, val in zip(key, value):
object.__setattr__(self, char, val)
else:
object.__setattr__(self, key, value)
__setattr__
与 __getattr__
不同,方法总是被调用,因此仅当我们要设置的项与值元组的长度相同时,我们才单独设置每个值。
>>> vector = Vector(4, 2)
>>> vector.x
4
>>> vector.xy
(4, 2)
>>> vector.xyz = 1, 2, 3
>>> vector.xyxyxyzzz
(1, 2, 1, 2, 1, 2, 3, 3, 3)
唯一的缺点是,如果您确实想分配一个元组(假设您有一个名为 size
的属性):
vector.size = (1, 2, 3, 4)
那么 s、i、z 和 e 将被分别赋值,这显然不是你想要的!
关于python - 如何装饰类并使用描述符访问属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43827908/
来自descriptor文档: A descriptor can be called directly by its method name. For example, d.__get__(obj).
概要 本人python理论知识远达不到传授级别,写文章主要目的是自我总结,并不能照顾所有人,请见谅,文章结尾贴有相关链接可以作为补充 全文分为三个部分装饰器理论知识、装饰器应用、装饰器延申
我正在查看 python 的描述 rune 档 here ,让我思考的陈述是: 对于物体,机械在 object.__getattribute__()转换 b.x进入 type(b).__dict__[
if((fd = creat(file_name,O_RDWR|S_IRWXU|S_IRWXG|S_IRWXO)) < 0){ perror("Create failed!");
长话短说Python 2.7.5,当使用描述符作为装饰器时,有没有办法传入参数(给 __init__ 方法)?或者如何使用带参数的方法装饰器 ( as here ) 访问类实例的属性? -- 我认为这
我试着用谷歌搜索一些关于它的东西。为什么非数据描述符适用于旧式类? 文档说他们不应该: “Note that descriptors are only invoked for new style ob
我升级到使用嵌入式 maven 3 的 netbeans 7。我有一个项目,其中包含许多模块和包含其他模块的模块。我的其他不依赖于内部项目的子模块可以在相同的配置下正常工作。在这种情况下,spring
我正在关注http://scikit-image.org/docs/0.11.x/auto_examples/plot_daisy.html ,但是不太清楚 desc[0],desc[1] 和 des
我有一个要求,其中有一个全局 FILE指针/描述符。其中一个函数将从该指针/描述符中读取。与FILE指针/描述符相关联的内部指针前进。此函数返回后,我想从同一个 FILE 指针/描述符中读取数据,并与
我正在编写一些描述符来封装数据验证,并想为它们编写测试。 我想知道是否应该通过在我的测试中创建描述符实例然后显式调用 __get__ 或 __set__ 方法来测试它们。 或者我应该在我的测试文件中创
我有这个 python 描述符: # Date Descriptor class DateAttribute(): def __init__(self, value=None):
分割: @font-face { font-family: 'RobotoLight'; src: url('../font/jura-demibold.eot'); src: url('../fon
我正在编写一个配置卷的存储自动化模块。我没有传递在存储 Controller 上实际创建卷所需的六个或更多参数,而是使用 __slots__ 创建了一个参数类,它被传递到 create 方法中,如下所
在我的应用程序中,我必须使用静态摄像头跟踪大学讲座中的讲师。目前我正在使用 Emgu CV 的默认 GPUHOGDescriptor,如果讲师的整个 body 都可见,它会很好用。在讲师站在 tabl
大家好,我正在使用 opencv3 和 contrib。问题是我想计算给定像素的筛选描述符(不使用检测到的关键点)。 我正在尝试用给定的像素构建一个关键点向量。但是,要创建关键点,除了像素位置外,我还
我正在使用 OpenCV 中的 HOGDescriptor 类进行对象检测。在我看来,该实现仅使用无符号渐变,因此无法区分亮->暗和暗->亮过渡,这是我真正需要的功能。有谁知道使用有符号梯度的 HOG
我目前正在使用 OpenCV 的 ORB 特征提取器,我确实注意到 ORB 描述符的存储方式很奇怪(至少对我来说是这样)(它基本上是一个 BRIEF-32,带有与我的问题无关的修改) .正如你们中的一
我想知道,在 MATLAB 中是否有针对“汽车”之类的对象而非人类的 HOG 描述符的任何实现? 但万一,只有人类,你能指导我找到那个代码,并给我一些提示,以改进代码以用于“汽车或摩托车等物体” 最佳
我正在尝试更好地理解描述符。 我不明白为什么在 foo 方法中描述符 __get__ 方法未被调用。 据我了解描述符 __get__ 当我通过点运算符访问对象属性或使用 __getattribute_
我想要一个类似于这个(无效)的结构: const uint8_t uArray[] = { uint8_t(sizeof(uArray)), 1, 2, 3 }; 并且 uArray[0] 应该是 4
我是一名优秀的程序员,十分优秀!