如何在派生的python类上操作decorator?

时间:2013-04-02 11:23:29

标签: python python-2.7 inheritance decorator python-decorators

我想使用装饰器对派生类做一些事情(例如注册类或其他东西)。这是我的代码:

from functools import wraps

class Basic(object):
    def __init__(self):
        print "Basic::init"

def myDeco(name):
    # define the decorator function that acts on the actual class definition
    def __decorator(myclass):

        # do something here with the information
        print name, myclass

        # do the wrapping of the class 
        @wraps(myclass)
        def __wrapper(*args, **kwargs):
            return myclass( *args, **kwargs)

        # return the actual wrapper here
        return __wrapper

    # return the decorator to act on the class definition
    return __decorator

@myDeco("test")
class Derived(Basic):
    def __init__(self):
        super(Derived, self).__init__()
        print "Derived::init"


instance = Derived()

会出现以下错误:

TypeError: must be type, not function

调用super中的Derived方法时。我假设变量Derived不再是type,而是函数__decorator

如何更改装饰器(仅限装饰器)来解决此问题?

2 个答案:

答案 0 :(得分:3)

您正在用函数替换已修饰的类,因此类定义失败。

具体来说,super(Derived, self).__init__()现在将函数传递给super()

>>> super(Derived, object())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be type, not function
>>> type(Derived)
<type 'function'>

类装饰器通常会更改类,添加,删除或更改它的属性,然后再次返回类对象。

您应该用新班级替换Derived,因为您的Derived.__init__()通过名称引用自己。用另一个类替换该名称将导致痛苦(例如无限递归)。

工作的示例类装饰器:

def my_deco(name):
    # define the decorator function that acts on the actual class definition
    def decorator(cls):

        # do something here with the information
        print name, cls

        setattr(class, name, 'Hello world!')

        # return the original, augmented class
        return cls

    # return the decorator to act on the class definition
    return decorator

答案 1 :(得分:0)

您的计划中有两个错误:

from functools import wraps

class Basic(object):
    def __init__(self):
        print "Basic::init"

def myDeco(name):
    # define the decorator function that acts on the actual class definition
    def __decorator(myclass):

        # do something here with the information
        print name, myclass

        # do the wrapping of the class
        class Wrap(myclass): # error 1
            realSuper = myclass # I dislike this. has anyone an other aproach
            def __new__(*args, **kwargs):
                return myclass.__new__(*args, **kwargs)

        # return the actual wrapper here
        return Wrap

    # return the decorator to act on the class definition
    return __decorator

@myDeco("test")
class Derived(Basic):
    def __init__(self):
        super(Derived.realSuper, self).__init__() # error 2
        print "Derived::init"


instance = Derived()

现在提供以下输出:

test <class '__main__.Derived'>
Basic::init
Derived::init

首先,你需要一个其他人指出的课程。

第二个super(Derived, self).__init__()导致无休止的递归:

Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    exec s
  File "<string>", line 32, in <module>
  File "<string>", line 28, in __init__
  File "<string>", line 28, in __init__
  File "<string>", line 28, in __init__
  File "<string>", line 28, in __init__

由于这个原因,请参阅下面的讨论。