python笔记--3--函数、生成器、装饰器、函数嵌套定义、函数柯里化
函数
函数定义语法:
def 函数名([参数列表]):
'''注释'''
函数体
函数形参不需要声明其类型,也不需要指定函数返回值类型
即使该函数不需要接收任何参数,也必须保留一对空的圆括号
括号后面的冒号必不可少
函数体相对于def关键字必须保持一定的空格缩进
Python允许嵌套定义函数
在定义函数时,开头部分的注释并不是必需的,但是如果为函数的定义加上这段注释的话,可以为用户提供友好的提示和使用帮助。
Python是一种高级动态编程语言,变量类型是随时可以改变的。Python中的函数和自定义对象的成员也是可以随时发生改变的,可以为函数和自定义对象动态增加新成员。
lambda表达式可以用来声明匿名函数,也就是没有函数名字的临时使用的小函数,尤其适合需要一个函数作为另一个函数参数的场合。
f = lambda x, z, y: x+y+z # 三个参数
print(f(3, 4, 5))
# g = lambda x, y=2, z=3: x+y+z # 一个参数,另两个有缺省参数
print(g(1))
#
print(g(1, z=4, y=5))
# L = [(lambda x: x**2), (lambda x: x**3), (lambda x: x**4)] # lambda表达式作为列表元素
print(L[0](2), L[1](2), L[2](2))
# 4 8 16 D = {'f1': (lambda: 2+3), 'f2': (lambda: 2*3), 'f3': (lambda: 2**3)} # lambda表达式作为字典的值
print(D['f1'](), D['f2'](), D['f3']())
# 5 6 8 L = [1, 2, 3, 4, 5]
print(list(map(lambda x: x+10, L))) # 模拟向量运算
# [11, 12, 13, 14, 15]
内置函数map()可以将一个函数作用到一个序列或迭代器对象上。
print(list(map(str, range(5))))
# ['0', '1', '2', '3', '4'] def add5(n): return n+5
print(list(map(add5, range(10))))
# [5, 6, 7, 8, 9, 10, 11, 12, 13, 14] def add(x, y): return x+y
print(list(map(add, range(5), range(5))))
# [0, 2, 4, 6, 8]
标准库functools中的reduce()函数可以将一个接受2个参数的函数以累积的方式从左到右依次作用到一个序列或迭代器对象的所有元素上。
from functools import reduce seq = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(reduce(lambda x, y: x+y, seq))
# def add(x, y):
return x+y print(reduce(add, range(10)))
#
print(reduce(add, map(str, range(10))))
#
内置函数filter将一个函数作用到一个序列上,返回该序列中使得该函数返回值为True的那些元素组成的filter对象。
seq = ['foo', 'x41', '?!', '***'] def func(x):
return x.isalnum() print(list(filter(func, seq)))
# ['foo', 'x41']
生成器
包含yield语句的函数可以用来创建生成器对象,这样的函数也称生成器函数。yield语句与return语句的作用相似,都是用来从函数中返回值。与return语句不同的是,return语句一旦执行会立刻结束函数的运行,而每次执行到yield语句并返回一个值之后会暂停或挂起后面代码的执行,下次通过生成器对象的__next__()方法、内置函数next()、for循环遍历生成器对象元素或其他方式显式“索要”数据时恢复执行。生成器具有惰性求值的特点,适合大数据处理。
Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处。
python有两种不同的方式提供生成器:
生成器函数:
常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
生成器表达式:
类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表。
注意,生成器只能遍历一次,再次遍历生成器将不会有任何记录。
def fib(n):
'''
普通函数
'''
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b fib(100)
# 0 1 1 2 3 5 8 13 21 34 55 89 def f():
'''
生成器函数
'''
a, b = 0, 1
while True:
yield a
a, b = b, a+b a = f()
for i in range(20):
print(a.__next__(), end=' ')
# 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 def gen():
yield 1
yield 2
yield 3 x, y, z = gen()
print(x, y, z)
# 1 2 3
函数嵌套定义
在Python中,函数是可以嵌套定义的。
def myMap(iterable, op, value): # 自定义函数
if op not in '+-*/':
return 'Error operator' def nested(item): # 嵌套定义函数
return eval(str(item)+op+str(value))
return map(nested, iterable) # 使用在函数内部定义的函数 print(list(myMap(range(5), '+', 5))) # 调用外部函数,不需要关心其内部实现
# [5, 6, 7, 8, 9]
print(list(myMap(range(5), '-', 5)))
# [-5, -4, -3, -2, -1]
print(list(myMap(range(5), '*', 5)))
# [0, 5, 10, 15, 20]
print(list(myMap(range(5), '/', 5)))
# [0.0, 0.2, 0.4, 0.6, 0.8]
可以使用嵌套函数定义可调用对象。
任何包含__call__()方法的类的对象都是可调用的。
def linear(a, b):
def result(x):
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) # 函数嵌套方式
print(taxes(5))
# 3.5 taxes = Linear(0.3, 2) # 类方式
print(taxes(5))
# 3.5
装饰器
装饰器(decorator)是函数嵌套定义的另一个重要应用。装饰器本质上也是一个函数,只不过这个函数接收其他函数作为参数并对其进行一定的改造之后返回新函数。类中的静态方法、类方法、属性等也都是通过修饰器实现的,Python中还有很多这样的用法。
def check_permission(func):
def wrapper(*args, **kwargs):
if kwargs.get('username') != 'admin':
raise Exception('Sorry. You are not allowed.')
return func(*args, **kwargs)
return wrapper class ReadWriteFile(object):
# 把函数check_permission作为装饰器使用
@check_permission
def read(self, username, filename):
return open(filename, 'r').read() def write(self, username, filename, content):
open(filename, 'a+').write(content)
# 把函数check_permission作为普通函数使用
write = check_permission(write) t = ReadWriteFile()
print('Originally.......')
print(t.read(username='admin', filename=r'e:/test/a123.txt'))
print('Now, try to write to a file........')
t.write(username='admin', filename=r'e:/test/a123.txt', content='\nhello world')
print('After calling to write...........')
print(t.read(username='admin', filename=r'e:/test/a123.txt')) '''
Originally.......
原始文本
Now, try to write to a file........
After calling to write...........
原始文本
hello world
'''
函数柯里化
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
偏函数
偏函数(partial function)和函数柯里化(function currying)是函数式编程中常用的技术。有时候我们在复用已有函数时可能需要固定其中的部分参数,这除了可以通过默认值参数来实现之外,还可以使用偏函数。
也可以使用标准库functools提供的partial()方法创建指定函数的偏函数。
from functools import partial def add3(a, b, c):
return a+b+c def add2(a, c):
return add3(a, 666, c) print(add2(1, 2))
# add2 = partial(add3, b=666) # 使用标准库functools提供的partial()方法创建指定函数的偏函数。
print(add2(a=1, c=2))
#
单参函数实现多参函数
函数柯里化除了可以实现偏函数类似的功能之外,还可以利用单参数函数来实现多参数函数,这要归功于Python对函数嵌套定义和lambda表达式的支持。
def func(a):
# lambda表达式实现
return lambda b: a+b print(func(3)(5))
# def func(a):
# 函数嵌套定义实现
def funcNested(b):
return a+b
return funcNested print(func(3)(5))
# def func(a):
# 多级函数嵌套实现多参数要求
def funcNested(b):
def funcNestedNested(c):
return a+b+c
return funcNestedNested
return funcNested print(func(3)(5)(8))
#
python笔记--3--函数、生成器、装饰器、函数嵌套定义、函数柯里化的更多相关文章
- Python学习之--函数/生成器/装饰器
Function,函数,主要是为了:1提高代码的复用程度,2将程序模块化. 定义函数 在Python中,使用def 用来定义函数,一般函数的定义如下: def name(arg1,arg2,....) ...
- python学习笔记(5)--迭代器,生成器,装饰器,常用模块,序列化
生成器 在Python中,一边循环一边计算的机制,称为生成器:generator. 如: >>> g = (x * x for xin range(10)) >>> ...
- Python开发——函数【装饰器、高阶函数、函数嵌套、闭包】
装饰器 装饰器本质就是函数,为其他函数添加附加功能. 原则: 不修改被修饰函数的源代码 不修改被修饰函数的调用方法 装饰器知识储备:装饰器 = 高阶函数 + 函数嵌套 + 闭包 案例:求函数运行时间! ...
- python中的迭代器&&生成器&&装饰器
迭代器iterator 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束. 迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外, ...
- python中的迭代器 生成器 装饰器
什么迭代器呢?它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了__iter__和__next__()(python2中实现next())方法的对象都是迭代器,_ ...
- python高级 之(二) --- 类装饰器
装饰器-初级 在不改变原有函数逻辑功能的基础上,为函数添加新的逻辑功能.使代码可读性更高.结构更加清晰.冗余度更低 简介 """ 闭包: 函数嵌套的格式就是闭包.写装饰器 ...
- Python全栈开发:装饰器实例
#!/usr/bin/env python # -*- coding;utf-8 -*- """ 1.将outer函数放入内存 2.遇见@ + 函数名,则将该函数转换为装 ...
- 柯里化函数之Javascript
柯里化函数之Javascript 定义 依据定义来说,柯里化就是将一个接收"多个"參数的函数拆分成一个或者很多个接收"单一"參数的函数.定义看起来是比較抽象的. ...
- 浅析 JavaScript 中的 函数 currying 柯里化
原文:浅析 JavaScript 中的 函数 currying 柯里化 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字 ...
- js函数柯里化,实现bind
1.柯里化: 把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术. 举个栗子: 一个计算两数之和的函数,需要传递两个参数,柯里化 ...
随机推荐
- 本地的html服务
本地的调试的时候, 我们服务器返回的cookie就会变的失效,因为你的本地服务器的域名不太对.
- cpu和gpu的区别和联系是什么
cpu和gpu的区别和联系是什么 一.总结 一句话总结:CPU:复杂任务,核少,做串行,计算能力只是CPU很小的一部分,处理复杂逻辑: GPU:简单任务,核多,做并行(大吞吐量),做显卡的图象单元计算 ...
- spring boot: @Retention注解 @Documented 注解 @Inherited 注解
http://www.jb51.net/article/55371.htm Retention注解 Retention(保留)注解说明,这种类型的注解会被保留到那个阶段. 有三个值:1.Retenti ...
- selenium与firefox版本不兼容
报错信息: org.openqa.selenium.firefox.NotConnectedException: Unable to connect to host 127.0.0.1 on port ...
- Unity3D重要知识点(转)
Unity3D重要知识点 数据结构和算法很重要!图形学也很重要!大的游戏公司很看重个人基础,综合能力小公司看你实际工作能力,看你的Demo. 1.什么是渲染管道? 是指在显示器上为了显示出图像而经过的 ...
- Thinkphp5.0 获取新增数据的ID
// 方法1 insertGetId方法新增数据并返回主键值使用getLastInsID方法: Db::name('user')->insert($data); $userId = Db::na ...
- _Meta 部分用法
model.UserInfo._meta.app_label #获取该类所在app的app名称 model.UserInfo._meta.model_name #获取该类对应表名(字符串类型) mod ...
- python 计数器类Counter的用法
简单操作: import collections A=['a','b','b','c','d','b','a'] count=collections.Counter(A) print(count) C ...
- LeetCode Target Sum
原题链接在这里:https://leetcode.com/problems/target-sum/description/ 题目: You are given a list of non-negati ...
- laravel 判断上传文件的类型和后缀
学习源头: https://blog.csdn.net/ddjjll8877/article/details/52249965 class FileUpdateController extends B ...