廖雪峰 Python教程 笔记 二
来源:互联网 发布:阿里云更改手机绑定 编辑:程序博客网 时间:2024/05/29 08:26
一、函数式编程
函数式编程接近与数学计算,抽象程度很高,相应的和计算机底层结构差异越大,效率不如C语言等高。
函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。
Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
1、高阶函数
函数 == 对象
函数是编程中,函数本身像一个对象一样,只是没有内部数据状态而,而函数名和变量名一样,指向某个函数对象的地址。
a、如f = abs
此时f就代表abs函数,能计算绝对值了。而将abs看做一个变量,它也是可变的!! 注意赋值是不带括号和参数的如果带了,就是执行了。
b、如果执行abs = 10,ads将不再能计算绝对值了,它将变成10这个数字。abs函数丢失了!,此时想要重新可用,需要重启Python交互式环境。
c、函数可以作为参数,返回值,容器元素等,被传递,存储等。
1.1 map/reduce
map就是映射,就想数学中的映射函数一样,是现实世界中一类十分常见的操作处理。map就是对一个序列中所有元素做某种变换,比如路径字符串替换前面的盘符。使用方式如下,先定义一个处理的函数f,然后放到map(f, Iterable)中,最后返回一个lterator惰性计算的序列。
>>> def f(x):... return x * x...>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])>>> list(r)[1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce:
reduce 和map的不同点是函数参数个数必须为2,即f(x1, x2),且操作序列的方式不同,它会将函数前一次计算的结果作为参数x1传入,然后取下一个数做x2传入,所以reduce的Iterable的元素个数至少为2,最后计算出一个结果。即 reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
1.2 filter
如名,filter对列表中的元素进行过滤,传入一个返回boolean的函数即可。
1.3 sort
如名,对列表中的元素进行排序,使用方式 sorted([36, 5, -12, 9, -21])
直接排序
sorted([36, 5, -12, 9, -21], key=abs)
添加排序函数,此排序函数返回一个值,然后根据返回值排序
sorted([36, 5, -12, 9, -21], key=abs, reverse=True)
反向
以上元素能方便的转换成key的,如果有多级参数排序这种不好转换成key的,在Python2里面可以传入cmp函数,但是在Python3里面去掉了,搞了一个很复杂的操作。
2、返回函数
即在函数中创建另一个函数,然后作为返回值返回,此函数并不会立即执行,需要在后面进行显示的的调用之后才会执行。此函数可以访问外部函数的参数和局部变量,本质上是持有它们的引用, 可以访问这个引用,以及改变它所指向的对象内部编变量的值,但是不能改变这个引用所指向的地址及对象,只能外部函数改变,这和Java的函数里面的匿名内部类相似,只是没有想Java里面一样final化,Python里面没有这个机制,所有会有后面一个问题q:,比如
def lazy_sum(*args): def sum(): ax = 0 for n in args: ax = ax + n return ax return sumf = lazy_sum(1, 3, 5, 7, 9)print(f())
特点:
1、每次调用外部返回的函数都是不一样的。
>>> f1 = lazy_sum(1, 3, 5, 7, 9)>>> f2 = lazy_sum(1, 3, 5, 7, 9)>>> f1==f2False
问题q:返回的函数是持有内部局部变量的引用,并不是直接拷贝一个,所以如果在下次执行之前,局部变量发生改变,函数持有的数据也是改变了的。比如下面这种:
def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fsf1, f2, f3 = count()>>> f1()9>>> f2()9>>> f3()9#因为在循环中定义的函数,等到后面某个时间执行时,内部函数(闭包)指向的变量的值已经改变了,变成了3。所以输出结果都是9
对于循环内的变量,如果一定要引用,方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
def count():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1, 4):
fs.append(f(i)) # f(i)立刻被执行,因此i的当前值被传入f()
return fs
再看看结果:
>>> f1, f2, f3 = count()>>> f1()1>>> f2()4>>> f3()9
因为传参时会创建一个新的引用,count函数对i的改变,不可能再影响f的j参数了。缺点是代码较长,可利用lambda函数缩短代码。
2、lambda表达式——匿名函数
lambda表达式的格式:lambda 参数列表:一个表达式
参数列表可以有多种参数,当然,它还可以像一个普通的函数一样,可以赋值传递等。
使用lambda可以简化函数的编写,更加快捷
lambda表达式可用来编写跳转表(jump table),就是行为的列表或字典。例如:
L = [(lambda x: x**2), (lambda x: x**3), (lambda x: x**4)]
* 3、函数装饰器 *
顾名思义,对函数加上一层包装,增加其功能。
例如
def log(func): @functools.wraps(func) def wrapper(x): print('start' + func.__name__) ret = func(x) print('end' + func.__name__) return ret return wrapper@logdef abs(x): if x > 0: return x else: return -xprint(abs(-11))
Python里面的函数名可以通过赋值改变其指向,所以其中的@log就相当于依据 abs = log(abs) 此时abs就相当于wapper函数,可在wrapper中接收相同的参数,返回函数值等。
使用装饰器之后,原函数的函数名会改变,Python提供了一个funtools函数进行处理 如上面的@functools.wraps(func)就是把wrapper的函数名称变回去,有些依赖签名的工具需要这个。
如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。比如,要自定义log的文本:
def log(text): def decorator(func): def wrapper(*args, **kw): print('%s %s():' % (text, func.__name__)) return func(*args, **kw) return wrapper return decorator
这个3层嵌套的decorator用法如下:
@log('execute')def now(): print('2015-3-25')
执行结果如下:
>>> now()execute now():2015-3-25
和两层嵌套的decorator相比,3层嵌套的效果是这样的:
>>> now = log('execute')(now)
我们来剖析上面的语句,首先执行log(‘execute’),返回的是decorator函数,再调用返回的函数,参数是now函数,返回值最终是wrapper函数。这样就能往第三层的函数里面传入相同的参数,并且可以使用第一层的属于Derector的参数了。巧妙的利用内部函数可以访问外部函数参数和局部变量的特性。Python里面函数基本也相当于对象了,外部函数的参数、局部变量被函数对象持有就不会消失。
4、functools提供的一些功能
functools.partial(f, a); 根据已有的函数f,自动传入部分参数,然后以此创建一个新的函数。编码中,通常需要创建某个函数的重载函数,原来函数所有参数都需要调用时传递,重载的只需传递部分的参数,另一部分在重载函数内传递默认值即可。functools.partial就是用来简化这种操作的。
Python的模块、包
1、定义
1、定义:
Python是将一个代码文件称作模块,也即模块就是一个.py文件。
包的定义和其它语言中一样,但是Python的包里面必须放上一个init.py文件,不管里面有无内容,否则不会被当做包处理。
2、模块文件头:
#!/usr/bin/env python3# -*- coding: utf-8 -*-' a test module '__author__ = 'Michael Liao'
第一、二行是标准注释,第一行让此文件可以直接在unix linux的机器上运行,第二行 表示使用标准的UTF-8编码,
第四行当做模块地注释,任何写在py文件开头的字符串都当做文档注释。
第六行的表示作者
这些可以不写,但一般写了更好
2、导入模块
1、导入语句
import module_name #直接导入,系统的或者是同级目录下的
from package_test import module_name #不是同级目录下的
对导入模块的搜索识别,默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中。
还可以手动指定要搜索的模块:
第一种直接修改System.path,运行结束后失效 sys.path.append('/Users/michael/my_py_scripts')
第二种方法是设置环境变量PYTHONPATH,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。
2、作用域
def private_function_name(xxx) 表示私有函数,_a或者__a私有的变量,这样前面加上两条一条或两条’‘的表示私有的变量,这只是告诉调用者不要访问这个函数或者变量,但是仍然是可以访问的,因为Python没有机制保证这个变量或者方法不能被访问。
3、其他的:
__name__
在Python中表示特殊变量,可以直接被引用,但是有特殊用途,代码中一般不创建这样的变量。
比如__doc__
表示模块文档,__author__
表示作者,
- 廖雪峰 Python教程 笔记 二
- 廖雪峰 Python教程 笔记
- 廖雪峰Python教程学习笔记
- 廖雪峰python教程笔记01
- 廖雪峰python教程学习笔记02
- python 笔记(廖雪峰教程)
- 廖雪峰python教程
- 廖雪峰python笔记
- 廖雪峰Python教程 学习笔记1 Python简介
- 廖雪峰Python教程 学习笔记2 安装Python
- 廖雪峰Python教程 学习笔记4 Python基础
- python笔记--廖雪峰站学习笔记(二)
- git学习(廖雪峰git教程)笔记 二
- python 字符串&格式化-----廖雪峰教程学习笔记
- 廖雪峰Python教程 学习笔记3 hello.py
- 廖雪峰Python教程学习笔记三-高级特性
- 廖雪峰Python教程学习笔记4-函数式编程
- 廖雪峰Python教程学习笔记5-面向对象编程
- QT构建项目时显示qmake错误
- chrome restclient Postman
- 11.10——基础布局 + xlv
- cx_freeze打包后的exe界面一闪而过解决方案
- RSA加密解密
- 廖雪峰 Python教程 笔记 二
- 学习总结
- 邮件系统使用规则
- 10.开源项目--git commit对象与存储
- Shop项目--1.注册新用户 验证码 前端校验工具validate 发送邮件激活
- 机器学习-人脸识别
- poj3276 Face The Right Way 反转问题
- 通过设置自定义动画实现回到顶部
- 最长子字符串