Python 试图编程一个;至“U类”;总装饰师
假设我已经定义了:Python 试图编程一个;至“U类”;总装饰师,python,decorator,python-decorators,Python,Decorator,Python Decorators,假设我已经定义了: def to_class(cls): """ returns a decorator aimed to force the result to be of class cls. """ def decorating_func(func): def wrapper(*args, **kwargs): return cls(func(*args, **kwargs)) return wrapper return decorator(de
def to_class(cls):
""" returns a decorator
aimed to force the result to be of class cls. """
def decorating_func(func):
def wrapper(*args, **kwargs):
return cls(func(*args, **kwargs))
return wrapper
return decorator(decorating_func)
我希望使用它来创建装饰器,将函数结果转换为给定类的对象。但是,这将不起作用:
class TestClass(object):
def __init__(self, value):
self._value = (value, value)
def __str__(self):
return str(self._value)
@staticmethod
@to_test_class
def test_func(value):
return value
to_test_class = to_class(TestClass)
as test_func将查找to_test_类,但找不到它。另一方面,在类定义之前将赋值放置到to_test_类也会失败,因为TestClass还没有定义
尝试将@to_class(TestClass)置于test_func的定义之上也会失败,因为方法是在类之前构造的(如果我没有错的话)
我发现的唯一解决方法是将to_test_类手动定义为装饰器,而不是从常规的“to_class”定义中返回
可能需要指出的是,这只是一个基本示例,但我希望在许多应用程序中使用to_类,例如在将返回值“插入”到类的构造函数之前修改它;我也希望将它用作其他类方法的装饰器
我确信有些人认为“to_class”装饰师是毫无意义的;相反,可以在修饰的方法中进行操作。尽管如此,我觉得它很方便,并且有助于提高可读性
最后,我想补充一点,这让我感兴趣20%是出于实际原因,80%是出于研究原因,因为我发现这是我对Python中的decorator的一般理解不够的。问题是,decorator在定义它所修饰的东西时会得到评估,所以在定义方法
test_func()
时,调用了decoratorto_test_class
,即使它已经存在,它应该处理的东西(classTestClass
)也不存在(因为这是在创建所有方法之后创建的)
也许您可以在使用类的位置使用占位符,然后(在创建类之后)在占位符位置填充该值(类)
例如:
lazyClasses = {}
def to_lazy_class(className):
""" returns a decorator
aimed to force the result to be of class cls. """
def decorating_func(func):
def wrapper(*args, **kwargs):
return lazyClasses[className](func(*args, **kwargs))
return wrapper
return decorating_func
class TestClass(object):
def __init__(self, value):
self._value = (value, value)
def __str__(self):
return str(self._value)
@staticmethod
@to_lazy_class('TestClass')
def test_func(value):
return value
lazyClasses['TestClass'] = TestClass
>>> TestClass.test_func('hallo')
<__main__.TestClass object at 0x7f76d8cba190>
lazyClasses={}
def to_lazy_类(类名):
“”返回一个装饰程序
旨在强制结果为cls类。”“”
def装饰功能(func):
def包装(*args,**kwargs):
返回lazyClasses[className](func(*args,**kwargs))
返回包装器
返回装饰函数
类TestClass(对象):
定义初始值(自身,值):
自我价值=(价值,价值)
定义(自我):
返回str(自身值)
@静力学方法
@to_lazy_类('TestClass'))
def测试函数(值):
返回值
懒散类['TestClass']=TestClass
>>>TestClass.test_func('hallo')
事实上,在类构造时,类对象本身尚未构造,因此您不能将其用作装饰器的基础
我能想到的一个解决方法是不要使用staticmethod
decorator。相反,在您自己的decorator内部,重新使用classmethod
decorator。通过这种方式,您可以确保Python至少为您传递关联类:
def to_class(func):
""" returns a decorator
aimed to force the result to be of class cls. """
def wrapper(cls, *args, **kwargs):
return cls(func(*args, **kwargs))
return classmethod(wrapper)
然后像这样使用它:
class TestClass(object):
def __init__(self, value):
self._value = (value, value)
def __str__(self):
return str(self._value)
@to_class
def test_func(value):
return value
演示:
>>> def to_class(func):
... """ returns a decorator
... aimed to force the result to be of class cls. """
... def wrapper(cls, *args, **kwargs):
... return cls(func(*args, **kwargs))
... return classmethod(wrapper)
...
>>> class TestClass(object):
... def __init__(self, value):
... self._value = (value, value)
... def __str__(self):
... return str(self._value)
... @to_class
... def test_func(value):
... return value
...
>>> TestClass.test_func('foo')
<__main__.TestClass object at 0x102a77210>
>>> print TestClass.test_func('foo')
('foo', 'foo')
>def to_类(func):
... “”返回一个装饰程序
…旨在强制结果为cls类。”“”
... def包装(cls、*args、**kwargs):
... 返回cls(func(*args,**kwargs))
... 返回类方法(包装器)
...
>>>类TestClass(对象):
... 定义初始值(自身,值):
... 自我价值=(价值,价值)
... 定义(自我):
... 返回str(自身值)
... @上课
... def测试函数(值):
... 返回值
...
>>>TestClass.test_func('foo')
>>>打印TestClass.test_func('foo'))
(‘foo’、‘foo’)
你的装饰器的通用版本并不容易;解决难题的唯一其他解决方法是使用元类黑客;请参见我在何处更详细地描述该方法
基本上,您需要进入正在构建的类名称空间,设置一个临时元类,然后依赖于至少存在一个类实例,然后装饰程序才能工作;临时元类方法与类创建机制挂钩,以便稍后检索构造的类
鉴于您正在使用此装饰器作为替代类工厂,这可能并不理想;如果有人使用您的修饰函数专门创建类实例,则元类将被调用得太迟。好吧,您忘记了类是传递给用classmethod修饰的方法的第一个参数,因此您可以这样编写它:
def to_this_class(func):
def wrapped(cls, value):
res = func(cls, value)
return cls(res)
return wrapped
class TestClass(object):
def __init__(self, value):
self._value = (value, value)
def __str__(self):
return str(self._value)
@classmethod
@to_this_class
def test_func(cls, value):
return value
x = TestClass('a')
print x.test_func('b')
对于普通方法不起作用(它们不能被制作成类方法),但是当然也有类似的方法使用
。\uuuuu class\uuuu
。很好的解决方案@Alfe:“普通”方法已经是实例的一部分,因此不需要返回类的实例。我们讨论的是包装它们的返回值“普通”方法不一定返回它们所在类的实例。但我想你的措辞把我弄糊涂了。你的意思可能是“不需要向他们传递类”(这就是我在提到\uu class\uuu
时的意思);由于这是一个董事会而不是PM会议,其他人可以稍后阅读,因此不仅仅是询问者的意图是相关的;还有其他人能从他的问题中理解什么,至少我对他的理解不同,所以你99.9%的可能性不是基于硬性数字(我的读者比例超过了0.1%);-)没错。我只是觉得他脑子里想的是一个普通的装饰师(甚至可能在课外的几个地方使用它),在这种情况下使用它遇到了麻烦。毕竟,强制结果为特定类的用例并不局限于静态方法。尽管需要添加“cls”。在希望使用不同的类的情况下是不可能的(毕竟,我们可能希望返回不同于c的类的实例)