4

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

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

当调用superin 方法时Derived。我假设变量Derived不再是 a type,而是函数__decorator实际上。

我如何需要更改装饰器(并且只有装饰器)才能解决此问题?

4

2 回答 2

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
于 2013-04-02T11:28:45.730 回答
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__

原因见下文讨论。

于 2013-04-02T11:30:48.363 回答