一、高级特性
1、切片
取list或tuple中的一部分元素,可使用切片操作符(:)。
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack'] #取前三个元素 >>>L[0:3] ['Michael', 'Sarah', 'Tracy'] #索引号第1个是0,可省略 >>>L[:3] ['Michael', 'Sarah', 'Tracy'] #取第1-3个字元素 >>>L[1:4] ['Sarah', 'Tracy', 'Bob']
也可以倒数取:
L = list(range(100)) >>> L [0, 1, 2, 3, ..., 99] #取最后10个数 >>>L[-10:] [90, 91, 92, 93, 94, 95, 96, 97, 98, 99] #取倒数第二个数 >>>L[-2,-1] [98]
也可以每N个取出元素:
>>> L[:10:2] #前10个数,每两个取一个 [0, 2, 4, 6, 8] >>> L[::5] #所有数,每5个取一个 [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
2、迭代
可用for循环遍历集合对象中所有元素的行为,称为迭代(Iteration)。
可迭代的对象:list、tuple、dict、set、字符串等。
d = {'a': 1, 'b': 2, 'c': 3} for key in d: #dict默认只迭代key值 print (key) for value in d.values() #迭代value值 print (value) for k,v in d.items() #迭代key和value值 print (k, v)
需要将list实现迭代时出现索引下标,可用enumerate函数:
for i, value in enumerate(['A', 'B', 'C']): print(i, value)
判断一个对象是否可迭代,可用collections模块的Iterable类型判断:
>>>from collections import Iterable >>>isinstance('abc', Iterable) #判断字符串是否可迭代 True >>>isinstance(123, Iterable) #判断整数是否可迭代 False
3、列表生成式
list(range(1,11))可以生成[1,2,3,....10]的list。
但如果要生成[1*1, 2*2, 3*3, ..., 10 * 10]这样的列表,除了用循环算法,还可以用列表生成式:[x * x for x in range(1,10)]
列表生成式的格式:[表达式 for x in range()]
for循环后加上if判断,可筛选for循环的结果:
>>> [x * x for x in range(1, 11) if x % 2 == 0] #仅出偶数的平方 [4, 16, 36, 64, 100]
也可以使用两层循环:
>>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
使用两个变量来生成List:
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' } >>> [k + '=' + v for k, v in d.items()] ['y=B', 'x=A', 'z=C']
if...else可以用在表达式当中:
[x if x % 2 == 0 else -x for x in range(1, 11)] [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
则list会直接生成出来。但是如果生成十万百万个这样的元素,则会消耗掉内存,可使用生成器来代替上面的列表生成式:
>>> g = (x * x for x in range(10))
def g(): for x in range(10): yield x*x return 'end'
函数体内包含yield则此函数为generator。
要调用该generator时,首先要生成一个generator对象,然后再用next()函数不断获得下一个yield的返回值。
o = g() while True: try: x = next(o) print('g:', x) except StopIteration as e: #使用StopIteration捕获return值 print('Generator return value:', e.value) break
也可以用for循环来不断获得返回值,这时不需要next()函数,也不会产生StopIntertaion错误。
for n in g(): print(n)
5、迭代器
可以for循环的数据类型有两种:
一种是集合类型,归属于Interable对象,比如:list、tuple、dict、set、str等;
一种是generator生成器,这类归属于Iterator对象。
把list
、dict
、str
等Iterable
变成Iterator
可以使用iter()
函数:
>>> isinstance(iter([]), Iterator) True >>> isinstance(iter('abc'), Iterator) True
二、函数式编程
函数式编程的重要特点:函数本身可以作为参数传入到另一个函数,还允许返回一个函数。
Python对函数式编程提供部分支持。
(一)函数作为参数传入:
1、map和reduce函数
map():接收两个参数,一个是函数(此函数只有一个参数),一个是Iterable,作用是将传入的函数作用到传入序列的每一个元素上。
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(f, [x1,x2,x3,x4]) = f(f(f(x1,x2), x3), x4)
from functools import reduce def add(x, y): return x + y reduce(add, [1, 3, 5, 7, 9]) #序列累积求和:25
2、filter函数
通过传入的函数,对序列进行过滤。传入的函数返回值必须是布尔值。
#去掉偶数,只保留奇数 def is_odd(n): return n % 2 == 1 list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) # 结果: [1, 5, 9, 15]
3、sorted排序函数
sorted()函数有三个参数,第一参数是要接受排序的序列,第二参数可选,用于在排序前对序列作用于每个元素,第三参数可选,默认为false,设为true则表示反向排序。
sorted(['bob', 'about', 'Zoo', 'Credit']) #按ascii码排序: ['Credit', 'Zoo', 'about', 'bob'] sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower) #对每个元素变小写,再按ascii码排序:['about', 'bob', 'Credit', 'Zoo'] sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True) #每个元素变小写,再按ascii码反向排序:['Zoo', 'Credit', 'bob', 'about']
(二)函数作为返回值:
函数可作为返回值返回,此时返回的函数体并不会立即执行。
#返回求和函数 def lazy_sum(*args): def sum(): ax = 0 for n in args: ax = ax + n return ax return sum f = lazy_sum(1, 3, 5, 7, 9) #调用函数f时,才会计算求和结果 f() #结果:25
注意:返回的函数体不要引用局部会变化的变量,否则会引起预想不到的结果。
(三)匿名函数
py的匿名函数写法:
lambda <参数>:返回函数体结果。
匿名函数的限制:只有有一个表达式,不用写return,返回值就是该表达式的结果。
f = lambda x:x*x #实际上就是: def f(x): return x*x
(四)装饰器decorator
当需要增强函数功能时,可使用装饰器decorator。
比如,在调用now()函数前显示自动打印函数日志。
def log(func): def wrapper(*args, **kw): print('调用 %s():' % func.__name__) return func(*args, **kw) return wrapper #要使用上面的封装器,则可这样使用: @log def now(): print('2020-04-14') #调用now() now() #显示: #call now(): #2020-04-14
(五)偏函数Partial function
偏函数的作用:把一个函数的某些函数用某个值固定,并返回一个新函数,可以简单调用。
举例:
int()函数可把字符串转换为整数,传入字符串时,会默认按十进制转换。此函数的第二个参数为默认值 10,可以用偏函数固定成其他值:
import functools int2 = functools.partial(int, base=2) int2('1000000') #结果:64
三、模块
模块作用:将代码利用模块分隔开,利于维护;
python:一个.py文件为一个模板,一个文件夹为一个package(文件夹下必须包含__init__.py)。
模块名起名规范:遵循py变量命名规范,不要使用中文和特殊字符,不要与系统模块名冲突;
示例:
mycompany
├─ web
│ ├─ __init__.py
│ ├─ utils.py
│ └─ www.py
├─ __init__.py
├─ abc.py
└─ utils.py
文件www.py的模板名为:mycompany.web.www。utils.py模块名分别有:mycompany.web.utils和mycompany.utils。
引用模块:
import 模块名
python在指定的路径下搜索对应的.py文件来加载模块。包括:当前目录、所有已安装的内置模块和第三模块目录。这些目录存放在sys模块下的path变量中。
>>> import sys >>> sys.path ['', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', ..., '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages']
添加模块搜索目录的方法:
(1)运行时添加:
>>> import sys >>> sys.path.append('/Users/michael/my_py_scripts')
这种方法在运行时添加,运行完后失效。
(2)设置PYTHONPATH环境变量
这种方式与PATH环境变量类似。
模块文件的编写规范:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- ' a test module ' __author__ = 'Michael Liao' import sys def test(): args = sys.argv if len(args)==1: print('Hello, world!') elif len(args)==2: print('Hello, %s!' % args[1]) else: print('Too many arguments!') if __name__=='__main__': test()
前两行为标准注释;
第4行是一个模块的文档注释,任何模块代码第一个字符串都被视为模块的文档注释;
第6行__author__变量是作者名。
而后的代码就是真正的代码部分。
最后两行,__name__变量是特殊变量,当模块在命令行模式运行时此变量为__main__字符串,常用于运行测试。
另外说明一点:
模块中的函数和变量都是公开的,无公有或私有化一说。只是我们自己可以规定_或__开头的应该业内口头规定为私有变量或函数,但实际上仍可以被外部调用。
安装第三方模块:
在安装了python后,可以使用pip(3版本为pip3)命令安装第三方库。
第三方库一般都在pypi.python.org 中注册。
安装常用模块,可以使用Anaconda更方便。下载地址:https://www.anaconda.com/download/