函数与装饰器:(1)函数

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://zhuyulab.blog.csdn.net/article/details/86764282

《流畅的python》 Day 3 & 4

函数:一等对象

  1. 在运行时创建
  2. 能赋值给变量或数据结构中的元素
  3. 能作为参数传递给函数
  4. 能作为函数的返回结果
    在python中,函数就是拥有以上性质的一等对象。

高阶函数:

接受函数为参数,或者把函数作为结果返回的函数是高阶函数(higher-order function)。

  1. map函数
    map 函数返回一个可迭代对象,里面的元素是把第一个参数(一个函数)应用到第二个参数(一个可迭代对象,这里是 range(11))中各个元素上得到的结果。
    map(factorial, range(11))
    filter用法与map类似 filter(function or None, sequence) -> list, tuple, or string
    map和filter一般可以用列表推导代替。

  2. 匿名函数lambda:
    除了作为参数传给高阶函数之外, Python 很少使用匿名函数。由于句法上的限制,非平凡的 lambda 表达式要么难以阅读,要么无法写出。
    lambda 参数:操作(参数)

add = lambda x, y: x + y
 print(add(3, 5))

任何对象也可以是函数

在python中实现实例方法__call__, 即可调用实例。

Python 最好的特性之一是提供了极为灵活的参数处理机制

假设有如下函数:

def tag(name, *content, cls=None, **attrs):
	pass
  1. 传入一个参数, 会作为name传入。
  2. 传入大于1个参数,第一个会作为name, 后面的会作为tuple被content捕获。
  3. 关键字参数,如tag(content='testing', name="img"), {content:testing}会被**attrs字典捕获。
  4. 如果字典关键词为cls, 则会传入cls,不会被attrs捕获。
  5. 也可以使用字典拆包(类似元组拆包)传参
my_tag = {'name': 'img', 'title': 'Sunset Boulevard', 'src': 'sunset.jpg', 'cls': 'framed'}
tag(**my_tag) 

装饰器

理解装饰器的核心只需要理解以下两段等效代码:
1.

@decorate
def target():
	print('running target()')

等效于

def target():
	print('running target()')
	target = decorate(target)

显然,decorate是一个接受func为参数,return func的函数。

函数装饰器在导入模块时立即执行,而被装饰的函数只在明确调用
时运行

闭包与自由变量

装饰器就涉及了函数内的函数(闭包问题),因此也会涉及自由变量。 比如:

def make_averager():
	series = []
	def averager(new_value):
		series.append(new_value)
		total = sum(series)
		return total/len(series)
return averager

运行结果为:

>>> avg = make_averager()
>>> avg(10)
10.0
>>> avg(11)
10.5

保存结果的series并没有作为局部变量直接消失,而是作为自由变量一直保存了一下。 这是因为series作为make_averager的局部变量,却被内部定义的函数定义了,此时就成为了自由变量,有点类似全局变量

注意,只有嵌套在其他函数中的函数才可能需要处理不在全局作用域中的外部变量。

nonlocal声明

但是正常情况下,自由变量不能在定义的内部函数中再次赋值处理,比如:

def make_averager():
	count = 0
	total = 0
	def averager(new_value):
		count += 1
		total += new_value
		return total / count
	return averager

这样就会报错,因为当我们使用count = count+1的时候,相当于声明了count为函数averager的局部变量。
一种解决办法是使用列表,因为对列表的append等操作并不会重新赋值,而是在原来值上进行操作(列表为可变对象)。
但是上述代码只需要加入一句话就可以运行:

nonlocal count, total

类似于global,这样就让count和total变成了自由变量。

标准库的两大重要装饰器

使用lru_cache做备忘
使用singledispatdispatch做重载

End

今天是大年三十,偷懒一下,就先记录这么多啦

展开阅读全文

没有更多推荐了,返回首页