Python


369 浏览 5 years, 4 months

10.1 被装饰对象

版权声明: 转载请注明出处 http://www.codingsoho.com/

被装饰对象

被装饰对象可以是下面三种

  • 函数
  • 类方法

函数装饰器 - 对函数进行装饰

它改变函数执行时的行为,通过下面方法来改变

  • 在函数定义时添加额外动作
  • 在原函数运行前后增加额外的代码
  • 调用时改变传递给原函数的参数

看下面代码

#decor
def hello(name):
    print("Hello {}".format(name))

hello = decor(hello)

装饰是一种重新绑定行为,

高阶函数

  • 函数式编程的概念
  • 函数能够作为参数被别的函数使用
  • 函数的返回值是其他函数

下面是一个对函数进行装饰的例子

def wrapper_decor(f):
    def wrapper(x):
    print("Call original function")
    f(x)
    print("Call original function done")
    return wrapper

@wrapper_decor
    def hello(name):
        print("How are you? {}".format(name))

净效果:

hello = wrapper_decor( hello)

装饰是一种重新绑定行为

装饰动作发生的时机

  1. 被装饰对象定义时
  2. 被装饰对象执行时

上面的例子装饰动作就是发生在执行时

下面例子中,装饰器并没有执行被装饰函数,这个装饰过程在定义时就已经完成

registry = set()

print registry                                                             #(1)
def register(func):
    registry.add(func)                                                     #(2)
    return func

@register
def Apple():
    print "Apple"

@register
def Banana():
print "banana"

print registry   

一个用户函数注册的装饰器。只为管理函数,并不修改函数的执行行为

  1. set([])
  2. 将func添加到registry中,但func函数本身并不会被执行
  3. set([<function Banana at 0x02575D70>, <function Apple at 0x02575BF0>])

对类进行装饰

@decor
class Foo():
    pass

Foo = decor(Foo)

下面是一个例子:

def context_decor(cls):
    def setup(self):
        print("Setup...")
    def teardown(self):
        print("Tear down")
    cls.setup, cls.teardown = setup, teardown
    return cls

@context_decor
class TestCase():
    def __init__(self, name):
          self.name = name

    def test_checkFunction(self):
        print("Inside test case: test_checkFunction")

通过继承修改类的定义,改变其行为

也可以用下面的方法

def context_decor(cls):
    class ProxyCls(cls):
        def setup(self):
            print("Setup...")
    def teardown(self):
            print("Tear down")
    return ProxyCls

@context_decor
class TestCase():
    def __init__(self, name):
        self.name = name

    def test_checkFunction(self):
        print("Inside test case: test_checkFunction")

对类方法装饰

class Foo():
    @decor
    def hello(self, name):
        print("Hello {}".format(name))

Foo.hello = decor(Foo.hello)     # Name re-binding
  • 参数传递问题 - self
  • self参数会被正确的传入,即使类方法被装饰过

对类方法装饰的例子

def wrapper_decor(f):
    def wrapper(x):
        print("Change behavior of original function")
        print("Call original function")
        f(x)
        print("Call originnal function done")
    return wrapper

class Foo():
    @wrapper_decor
    def bar(self, x):
        print(x)