Python函数的高级用法

来自CloudWiki
跳转至: 导航搜索

函数的高级用法(可选)

函数嵌套定义

  • Python允许函数的嵌套定义,在函数内部可以再定义另外一个函数。
>>> def myMap(iterable, op, value):     #自定义函数
   if op not in '+-*/':
       return 'Error operator'
   def nested(item):                   #嵌套定义函数
       return eval(repr(item)+op+repr(value))
   return map(nested, iterable)        #使用在函数内部定义的函数
>>> list(myMap(range(5), '+', 5))       #调用外部函数,不需要关心其内部实现
[5, 6, 7, 8, 9]
>>> list(myMap(range(5), '-', 5))
[-5, -4, -3, -2, -1]
def f2(n,i):
    cache2 = dict()
    
    def f(n,i):
        if n==i or i==0:
            return 1
        elif (n,i) not in cache2:
            cache2[(n,i)] = f(n-1, i) + f(n-1, i-1)
        return cache2[(n,i)]
    
    return f(n,i)
  • 使用标准库提供的缓冲机制进行改写和优化。
from functools import lru_cache

@lru_cache(maxsize=64)
def cni(n, i):
    if n==i or i==0:
        return 1
    return cni(n-1, i) + cni(n-1, i-1)

可调用对象

  • 函数属于Python可调用对象之一,由于构造方法的存在,类也是可调用的。像list()、tuple()、dict()、set()这样的工厂函数实际上都是调用了类的构造方法。另外,任何包含__call__()方法的类的对象也是可调用的。
  • 下面的代码使用函数的嵌套定义实现了可调用对象的定义:
def linear(a, b):
    def result(x):              #在Python中,函数是可以嵌套定义的
        return a * x + b
    return result               #返回可被调用的函数
  • 下面的代码演示了可调用对象类的定义:
class linear:
    def __init__(self, a, b):
        self.a, self.b = a, b
    def __call__(self, x):         #这里是关键
        return self.a * x + self.b
  • 使用上面的嵌套函数和类这两种方式中任何一个,都可以通过以下的方式来定义一个可调用对象:
taxes = linear(0.3, 2)
  • 然后通过下面的方式来调用该对象:
taxes(5)

修饰器

  • 修饰器(decorator)是函数嵌套定义的另一个重要应用。修饰器本质上也是一个函数,只不过这个函数接收其他函数作为参数并对其进行一定的改造之后使用新函数替换原来的函数。
  • Python面向对象程序设计中的静态方法、类方法、属性等也都是通过修饰器实现的。
def before(func):                       #定义修饰器
    def wrapper(*args, **kwargs):
        print('Before function called.')
        return func(*args, **kwargs)
    return wrapper

def after(func):                        #定义修饰器
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        print('After function called.')
        return result
    return wrapper

@before
@after
def test():                             #同时使用两个修饰器改造函数
    print(3)
#调用被修饰的函数
test()