函数是组织好的,可重复使用的,用来实现单一,或相关功能的代码块。python
函数分为 Python 程序内置函数,用户自定义的函数。将代码定义为函数,有以下好处:git
使用 def 关键字定义一个函数,后面紧跟函数名,小括号也必不可少,语法以下:算法
def func(): 函数体
函数在执行时,首先将函数体加载到解释器中,可是不会运行,只有当调用函数后才会执行,函数名+小括号便可调用函数:express
def func(): 函数体 func() # 调用函数
有时咱们须要函数返回一些数据来报告执行的结果,全部就须要有返回值,只须要在函数中添加 return 关键字,后面跟着返回值便可。编程
def func(): return 1
return 将返回值传递给函数自己,咱们只要调用函数,再将函数赋值给变量便可得到返回值:json
def func(): return 1 res = func() # 得到返回值,并赋值给变量 res print(res) 1
返回值能够是 0 个,也能够是 1 个 或多个:数组
def func(): # return # return 1 return 1, 2 res = func() print(res) None 1 (1, 2)
函数的参数能够用函数实现个性化,大体分为两类:数据结构
形参只有在调用时才分配内存单元,调用结束,就释放。仅在函数内部有效,不能在函数外部使用。闭包
实参能够是常量、变量、表达式、函数,占用内存空间。app
形参又分为:默认参数、位置参数、关键字参数以及可变长参数,而默认参数即在函数定义时默认赋予某个形参一个值。若函数调用时,不传入实参,函数使用默认值,不然使用实参。
def func(x=2): # x 默认为 2 return x + 2 res = func() # 即便不传入实参函数也能正常运行 print(res)
普通的参数即为位置参数,在调用时实参必须与形参一一对应。而关键字参数,能够不用考虑位置的关系,只须要名字相同便可。
def func(name, words): print(name: words) func('Hello', words='world') # 第一个为位置参数,第二个为关键字参数 func(words='World', name='Hello') # 不用考虑位置
Tips:位置参数必须在关键字参数后面
可变长参数是一种参数组,它能够是多个参数,只须要在参数前加上星号(*)便可。它能够增长函数可拓展性,当你不知道定义的函数须要定义几个参数时,使用它很方便。
可变长参数分为:*args 和 **kwargs两类:
*args
*args 、**kwargs 是 Python 官方定义的参数名,也能够是其余名字,可是最好使用它,以便于辨认。
def func(*args): print(args) print('有 %d 个参数' % len(args)) print('第三个参数是:', args[2]) func('P', 'y', 't', 'h', 'o', 'n') func('Python', 123, '爬虫')
('P', 'y', 't', 'h', 'o', 'n') 有 6 个参数 第三个参数是: t ('Python', 123, '爬虫') 有 3 个参数 第三个参数是: 爬虫
Tips:若是可变长参数后面还有参数,要将其定义为关键字参数,不然会被收集成可变长参数里面。建议在使用可变长参数时,可将其余参数设置为默认参数,或关键字参数,这样不易混淆。
def func(*args, extra=16): # def func(*args, extra): print(args) print(extra) func(1,2,3) #func(5,6, extra=18) (1, 2, 3) 16 (5, 6) 18
星号()既可用来收集打包参数,也能够用来“解包”参数。当传入的参数时列表、元组、字典以及集合时,可变长参数将会将其整个打包成只有一个元组的参数,而在其前面添加一个星号( ),就能够将里面的元素一个个都解出来。
def func(*args): print(args) l = [1, 2, 3] t = (4, 5, 6) d = {'name':'rose', 'age': 18} func(l) func(*l) func(t) func(*t) func(d) func(*d)
([1, 2, 3],) (1, 2, 3) ((4, 5, 6),) (4, 5, 6) ({'name': 'rose', 'age': 18},) ('name', 'age')
**kwargs
另外一种可变长参数就是 **kwargs,它将传入的实参打包成一个字典,一样地也支持 “解包”。
def func(x, **kwargs): print(x) print(kwargs) print('总共有 %d 个参数' % len(kwargs)) print('这些参数分别为:', kwargs) func(20, name='rose', age=18)
20 {'name': 'rose', 'age': 18} 总共有 2 个参数 这些参数分别为: {'name': 'rose', 'age': 18}
解包,当传入的参数是字典时:
def func(gender, **kwargs): print(gender) print(kwargs) print('总共有 %d 个参数' % len(kwargs)) print('这些参数分别为:', kwargs) t = {'name': 'rose', 'age': 18} func('female', **t)
female {'name': 'rose', 'age': 18} 总共有 2 个参数 这些参数分别为: {'name': 'rose', 'age': 18}
当既有 *args,又有 **kwargs,以及位置参数和位置参数时:
def func(gender, country='China', *args, **kwargs): print(gender, country) print(args) print(kwargs) func('male', 'America', 20, 30, name='rose', age=19)
male America (20, 30) {'name': 'rose', 'age': 19}
函数文档即用来描述函数功能的文档,可让别人更好地理解你的函数,定义函数文档是个好的习惯。
def func(x): """ 计算一个数加一 :param x: :return: """ x += 1 return x res = func()
在 Python 中函数和过程是分开的,函数(function)与过程(procedure)的区别:
严格来讲 Python 没有过程,只有函数,由于即便没有返回值,也会默认返回一个 None。
def func(): print('Hi') res = func() print(res) Hi None
变量的做用域即变量可见性,也就是可用范围,通常编程语言分为:全局变量(global variable)和局部变量(local variable)。
当全局变量与局部变量同名是,在子程序中局部变量起做用,在外面全局变量起做用。
# 首先加载整个函数(不执行),调用函数执行函数内部,打印 tom,最后打印 rose name = 'rose' # 全局 def test(): name = 'tom' # 局部 print(name) test() print(name) tom rose
1. global 关键字
全局变量的做用域是整个程序,函数内部亦可访问。可是不要在函数内部试图修改全局变量,这是由于 Python 使用了屏蔽(shadowing)的方式去 保护全局变量。一旦在函数内部修改,则会在函数内部建立一个如出一辙的局部变量。
name = 'rose' def test(): name = 'tom' print(name) test() print(name) tom rose
从上面例子能够看出,全局变量的值没有改变。可是 Python 是支持在函数内部修改全局变量的,只须要在变量前面加上一个 global 关键字便可:
name = 'rose' def test(): global name name = 'tom' print(name) test() print(name) tom tom
总结:当全局与局部变量名字相同时,函数内部优先读取局部变量。为了更好地区分全局与局部变量,通常地全局变量名尽可能使用大小,局部变量名使用小写。
2. 内嵌函数
函数支持嵌套,即一个函数中嵌套另一个函数,这种函数叫内嵌函数或内部函数。
name = 'rose' # (1) def fun1(): # (2) name = 'tom' # (5) def fun2(): # (6) name = 'lila' # (8) fun2() # (7) print(name) # (9) print(name) # (3) fun1() # (4) print(name) # (10) rose tom rose
Tips:内部函数只能在内部调用,外部调用会报 NameError
闭包(closure)是函数式编程中的一个重要数据结构,Python 中认为若是在一个内部函数里,对在外部做用域(但不是全局做用域)的变量进行引用,那么这个内部函数就是闭包(closure)。
def fun1(x): def fun2(y): return x * y return fun2 a = fun1(6) # a 接收的是 fun2() 的内存地址 print(a) b = a(5) # a(5) 至关于调用 fun2() print(b) # 上述能够简写 # res = fun1(6)(5) # print(res) <function fun1.<locals>.fun2 at 0x00000000026F48C8> 30
从上面的例子能够看出,内部函数 fun2()对外部函数 fun1()的变量 x (不是全局变量)进行了引用,那么 fun2()便是闭包。
nonlocal 关键字
但须要注意的是不能在外部函数外面调用内部函数,对外部函数的局部变量只能进行访问,不能修改。
def fun1(): name = 'rose' def fun2(): name = 'tom' return name print(name) return fun2 fun1()() rose # 外部函数局部变量 name = ‘rose' 并无被修改
若是在内部函数中想修改外部函数的局部变量能够用 nonlocal 关键字,可是须要注意的是它不能修改全局变量。
def fun1(): name = 'rose' def fun2(): nonlocal name # 添加 nonlocal 关键字 name = 'tom' return name print(name) return fun2 fun1()() tom # 外部函数局部变量 name = ‘rose' 已经被修改
Python 程序按程序执行,遇到函数,先加载到到内存,只有当调用函数时,才会运行函数体。所以一个函数能够做为 变量在另外一个函数内部调用执行,前提是第一个函数须要先加载。
首先加载 f1()、f2(),再调用 f1(),执行 f1()里的函数体,最后调用 f2(),执行 f2()里的函数体:
def f1(): # (1) print('from f1') # (4) f2() # (5) def f2(): # (2) print('from f2') # (6) f1() # (3) from f1 from f2
另外一种状况:
def f2(): print('from f2') def f1(): print('from f1') f2() f1() from f1 from f2
第三种状况,调用 f2()时,由于 函数 f2()还未加载,致使出错(NameError: name 'f2' is not defined
):
def f1(): print('from f1') f2() def f2(): print('from f2') f1()
在函数内部,能够调用其余函数,若是在调用过程当中直接或间接调用自身,那么这个函数就是递归函数。
递归函数特征:
函数调用是经过栈(stack)实现,每调用一次,栈就会增长一层栈帧,函数返回,则减小一层。因为栈的大小有限,全部递归过多,就会致使栈溢出。
def func(n): print(n) if int(n/2) == 0: # 结束条件 return n res = func(int/2) # 调用自身 return res func(10) 10,5,2,1
递归问路
使用递归函数,实现一次递归问路操做。
import time person_list = ['rose', 'tom', 'lila', 'json', 'john'] def ask_way(person_list): """ 问路操做 :param person_list: 被问的人 :return: """ print('-'*60) if len(person_list) == 0: return '没人知道' person = person_list.pop() if person == 'json': return '%s 我知道 xxx 怎么走,它在 xxx' % person print('你好,%s,请问 xxx 在哪里?' % person) print('%s 回答道:我也不知道,我帮你去问问 %s' % (person, person_list)) time.sleep(2) res = ask_way(person_list) return res res = ask_way(person_list) print(res)
------------------------------------------------------------ 你好,john,请问 xxx 在哪里? john 回答道:我也不知道,我帮你去问问 ['rose', 'tom', 'lila', 'json'] ------------------------------------------------------------ json 我知道 xxx 怎么走,它在 xxx
二分查找
data = [1,3,6,7,9,12,14,16,17,18,20,21,22,23,30,32,33,35] def find_num(data, num): """ 使用二分查找法,查找出一个数字的位置 """ print(data) if len(data) > 1: mid = int(len(data)/2) if data[mid] == num: print('找到数字', data[mid]) elif data[mid] > num: print('要找的数字在 %s 右边' % data[mid]) return find_num(data[0:mid], num) else: print('要找的数字在 %s 左边' % data[mid]) return find_num(data[mid+1:], num) else: if data[0] == num: print('找到数字', data[0]) else: print('要找的数字不在列表中') find_num(data, 66)
[1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35] 要找的数字在 18 左边 [20, 21, 22, 23, 30, 32, 33, 35] 要找的数字在 30 左边 [32, 33, 35] 要找的数字在 33 左边 [35] 要找的数字不在列表中
尾调用又称为为递归,指的是函数在最后一步调用另外一个函数的过程(最后一行不必定是最后一步)。
# bar 在 foo 内为尾调用 def bar(n): return n def foo(m): return bar(m)
# bar 在 foo 内不是尾调用,最后一步为 return y def bar(n): return n def foo(m): y = bar(m) return y
# bar一、bar2 在 foo 内都是尾调用 def bar1(n): return n def bar2(n): return n+1 def foo(x): if type(x) is str: return bar1(x) elif type(x) is int: return bar2(x)
尾调用优化
定义 a 函数,a 内调用 b,b 调用 c,在内存中造成一个调用记录,又称为调用帧(call frame)。用于存储调用位置和内部变量等信息,即(a——b——c),直至 c 返回结果给 b,c 的调用记录消失。b 返回给 a,b 的调用记录消失,a 返回结果,a 的调用记录消失,全部记录都是先进后出,造成一个调用栈(call stack)
匿名函数即不须要显示地指定函数名的函数,Python 容许使用 lambda 关键字来建立一个匿名函数,匿名函数也被称为 lambda 表达式。
lambda x:x+2 lambda x,y,z:(x+1, y+1, z+1) # 多个参数
冒号左边是原函数参数,能够有多个参数,逗号分隔便可,冒号右边为返回值。对于有些结构比较简单的函数,能够直接定义为匿名函数:
def func(x): return x+2 s = func(3) print(s)
上述函数可直接定义一个匿名函数:
f = lambda x:x+2 f(3) # 调用
匿名函数常与其余函数搭配使用:
# 将 匿名函数当作参数传入 calc 中 def calc(func, li): ret = [] for i in li: res = func(i) ret.append(res) return ret li = [2, 3, 4, 6, 8] calc(lambda x:x+1, li) [3, 4, 5, 7, 9]
lambda 表达式的做用:
当今编程的三种方法论:
函数式编程(函数+数学函数),更贴近数学,是一种抽象成都很高的编程范式,不容许函数有变量。但 Python 不是严格意义上的函数式编程,由于它容许有变量。
函数式编程特色:
函数即变量
def foo(n): print(n) def bar(name): print(name) foo(bar('rose')) rose None
上面例子中,bar('rose') 打印 rose,没有返回值,所以 foo(bar('rose'))
至关于 foo(None)
。
返回值是函数
返回函数自己:
def handle(): print('from handle') return handle # 返回函数自己内存地址 h = handle() # 使用变量 h 接收 h() # 再调用函数自己 from handle from handle
返回别的函数:
def test(): print('from test') def test1(): print('from test1') return test # 返回 test 函数的内存地址 n = test1() # 接收 n() # 至关于调用 test()
函数式编程的两个特征:函数即变量,返回值是函数,只需知足其中一个条件,便可成为高阶函数。
def add(x, y, f): return f(x)+f(y) print(add(-5, 6, abs)) 11
上面例子中,内置函数 abs 做为参数传入函数 add。
map(function, sequence)
函数是高阶函数的一种,它有两个参数:第一个为函数,另外一个接收一个序列。
其做用是将序列中每一个元素(for 循环),做为函数参数传入第一个参数中,直至序列中每一个元素都被循环,返回一个迭代器对象,用 list 可得到结果。
# 对列表 l 中每一个元素加 1 li = [2, 3, 4, 5, 6] def add_one(x): return x+1 res = map(add_one, li) print(res) print(list(res)) <map object at 0x0000000002C5C0B8> [3, 4, 5, 6, 7]
上面例子中 map 函数将列表 li 的每一个中每一个元素取出,再传入 add_one 中。
一样地也可使用 lambda 表达式与 map 函数简写:
res = map(lambda x:x+1, li)
传入两个列表:
res = map(lambda x, y: x+y, [1, 3, 5], [2, 4, 6]) print(list(res))
filter(function or None, iterable)
函数有两个参数:第一个能够是函数也能够是 None,第二个为可迭代对象。
第一个参数为函数:
# 过滤掉以 123 结尾的名字 names = ['rose_123', 'lila_123', 'john'] def filter_123(x): return not x.endswith('123') # 返回没有以 123 结尾的名字 res = filter(filter_123, names) list(res) john
使用 lambda 表达式简写:
res = filter(lambda x: not x.endswith('123'), names) list(res)
第一个参数为 None:
res = filter(None, [1, 2, 0, True, False]) list(res) [1, 2, True]
reduce(function, sequence[, initial])
函数三个参数:第一个为函数,第二个为序列,第三个可选为初始值。
Python3 把 reduce 函数集成到 functools 模块中,所以每次使用时,须要from functools import reduce
。它能够把一个函数做用在一个序列上,这个函数必须接收两个参数。首先将序列中的前两个元素取出,传入函数中,返回值再与序列中接下来的元素作累积计算,直至序列中的每一个元素都被循环。
求列表中全部元素的乘积:
常规:
nums = [1, 2, 3, 100] def reduce_test(func, array): res = array.pop(0) for i in array: res = func(res, i) return res s = reduce_test(lambda x,y: x*y, nums) print(s) 600
reduce:
from functools import reduce nums = [1, 2, 3, 100] res = reduce(lambda x,y : x*y, nums) print(res) 600
首先将 nums 前两个元素,即 一、2 传入lambda x,y: x*y
中,返回 x*y
。再将 3 传入,最后将 100 传入,至关于(((1*2)*3)*100)
。
指定初始值:
from functools import reduce nums = [1, 2, 3, 100] res = reduce(lambda x,y : x*y, nums, 6) # 至关于 (((6*1)*2)*3)*100 print(res) 3600
累加计算:
from functools import reduce reduce(lambda x,y: x+y, [1, 2, 3, 4, 5]) 15
排序算法在程序中是常常用到的算法,不管是冒泡仍是快排,其核心都是比较两个元素的大小。
sorted(iterable, key, reverse)
函数也是一个高阶函数,在列表内置方法中咱们就已经接触到了,它能够对一个列表进行排序,默认从小到大。
sorted([1, -3, 2]) [-3, 1, 2]
此外,它还接收一个 key 函数来自定义排序,key 函数做用在列表中的每一个元素上,再进行比较,如按绝对值排序:
sorted([1, -3, 2], key=abs) [1, 2, -3]
第三个参数 reverse,能够反向排序:
sorted([1, -3, 2], key=abs, reverse=True) [-3, 2, 1]
上面都是针对数字的排序,直接比较其大小便可。可是对于字符串来讲,通常地都是比较其首字母在 ASCII 中的大小:
sorted(['b', 'a', 'Z']) # 由于在 ASCII中 Z<a ['Z', 'a', 'b']
如今咱们不想按照 ASCII 来排序,而是按照字母表排序,那么咱们能够经过指定 key 函数,将全部字符串转换为大写或小写便可实现:
sorted(['b', 'a', 'Z'], key=str.upper) ['a', 'b', 'Z']
functools 模块提供了不少功能,其中一个就是偏函数(partial )。
当函数的参数个数太多,须要简化时,使用 functools.partial
建立一个偏函数,这个新的函数能够固定住原函数的部分参数,从而调用更简单。
语法结构:
from functools import partial func2 = partial(func, *args, **kwargs) # 第一个参数:要固定的函数,第二个:原函数的位置参数,第三个:关键字参数
第一个参数能够是自定义的函数,也能够是内置函数。
int() 函数能够把字符串转换为整型,默认按照十进制转换:
>>> int('123') 123
int() 函数还额外提供一个 base 参数,若是传入 base,就能够作 N 进制转换:
>>> int('123', base=8) # 按照八进制转换 83
内置函数
假如要转换大量的二进制字符串,每次都要传入 base,就会很繁琐。咱们能够利用偏函数(partial)将 base=2
固定住,定义一个新的函数,每次只须要传入要转换的字符串便可:
>>> from functools import partial >>> int2 = partial(int, base=2) # 将 base = 2 固定住 >>> int2('100') # 至关于 kw={'base': 2} int('100', **kw) 4
自定义函数
当咱们调用某个函数,已知某个参数的值时,能够将其固定住(至关于设定默认值):
from functools import partial def add(x, y): return x % y add2 = partial(add, 5) # 自动将 5 做为 *args 的一部分放在最左边,也就是 5 % 100 print(add2(100)) # 101
将列表中年龄小于等于 18 岁的人过滤出来。
people = [ {'name': 'rose', 'age': 18}, {'name': 'lila', 'age': 30}, {'name': 'tom', 'age': 60} ] res = filter(lambda p: p.get('age') <= 18, people) print(list(res)) [{'name': 'rose', 'age': 18}]
函数分为 Python 内置函数和自定义函数,内置函数有不少,可是真正能用到的也比较少。
# abs():求一个数字的绝对值 >>> abs(-5) 5 # all(iterable):判断序列中全部元素是否为 True,若是序列为空,也返回 True,返回布尔值 >>> all([1, 2, 0]) False # any(iterable):序列中元素 bool(x),只要有一个为 True,则返回 True,若是序列为空,返回 False >>> any([]) False >>> any(['', 0, 1]) True # bin(number):十进制转二进制 >>> bin(10) '0b1010' # hex(number):十进制转十六进制 >>> hex(10) '0xa' # bool():转换为布尔类型 >>> bool(0) False >>> bool(None) False >>> bool('') False # bytes(obj,encoding=None):将对象编码(二进制) # bytes(obj,encoding=None).decode(None):解码,用什么编码就应用什么解码 >>> name = '你好' >>> bytes(name, encoding='utf-8') b'\xe4\xbd\xa0\xe5\xa5\xbd' >>> bytes(name, encoding='utf-8').decode('utf-8') '你好' # chr(i):返回一个数字在 ASCII 中对应的值 >>> chr(90) 'Z' # ord(obj):查询一个字符咋 ASCII 中的对应的数字 >>> ord('Z') 90 # dict():建立一个字典 >>> d = dict() >>> type(d) <class 'dict'> # dir(obj):返回一个对象的全部方法名字 >>> dir(str) # help(obj):查看帮助文档 >>> help(list.append) Help on method_descriptor: append(...) L.append(object) -> None -- append object to end # dirmod(x,y):返回一个元组,结果为 x/有的商和余数,通常用做网页分页 >>> divmod(10, 3) (3, 1) # id(obj):查看一个对象的内存地址 >>> id(10) 1750035808 # globals():查看全局变量 # locals():查看局部变量 # pow(x,y[,z]):幂运算,z 可选, pow(x,y,z)至关于 (x**y)%z >>> pow(10, 3) 1000 >>> pow(10, 3, 4) 0 # reversed(iterable):反转一个序列 >>> list(reversed('abc')) ['c', 'b', 'a'] >>> list(reversed([1, 2, 3])) [3, 2, 1] # round(number,ndigits):四舍五入,保留几位有效小数 >>> round(4.5) 4 >>> round(4.564, 2) 4.56 # set(iterable):转换成集合、建立一个集合 >>> set('123') {'2', '3', '1'} >>> s = set() >>> type(s) <class 'set'> # slice(statr,stop[,step]):序列切片/分片 >>> l = 'hello' >>> s = slice(2, 3) >>> l[s] 'l' # str():转换为字符串 >>> str(123) '123' # sum(iterable, start=0):求序列中全部元素的和,还可指定 >>> l = [1, 2, 3, 4] >>> sum(l) 10 >>> sum(l, 1) 11 # tuple():转换为元组 >>> tuple(['a', 1]) ('a', 1) # vars(obj):返回对象的属性和属性值的字典对象。 >>> vars() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'name': '你好', 'd': "{'name:': ' rose'}", 's': slice(2, 3, None), 'p': {'name': 'rose', 'age': 18, 'gender': 'male'}, 't': <zip object at 0x0000000002D9FF08>, 'i': ('c', 3), 'age': {'rose': 18, 'tom': 19}, 'li': 'hello', 'l': [1, 2, 3, 4]} >>> vars(str) .... # __import__():当模块名是字符串是,可使用。 >>> module_name = 'test' >>> __import__(module_name) <module 'test' from 'C:\\Users\\HJ\\Anaconda3\\lib\\test\\__init__.py'> >>> import module_name Traceback (most recent call last): File "<stdin>", line 1, in <module> ModuleNotFoundError: No module named 'module_name'
1. eval()
eval(expression,[globals[,locals])
,用于执行一个字符串表达式,并返回表达式值,能够去掉字符串的引号。
>>> d = "{'name:': 'rose'}" >>> type(d) <class 'str'> >>> s = eval(d) >>> type(s) <class 'dict'>
字符串中表达式的值,也能够计算:
>>> express = '1*2+3' >>> eval(express) 5
2. hash()
hash(obj)
作哈希运算,无论对象有多长,通过哈希运算后的值长度都相同,也不能根据 hash 值反推出原始对象。
可用于校对软件/文件是否被别人篡改,还可用于判断软件或文件是否下载完整(检验官方给出的 hash 值与本身下载完毕 hash 的值是否相同)
>>> hash('abc') 5994226220732616244 >>> hash('123') -3466646395452377901
3. isinstance()、type()
两个都是用于判断数据类型,官方建议使用 isinstance。
>>> type(123) <class 'int'> nums = '123' if type(nums) is str: res = int(nums) + 1
isinstance(x,A_tuple)
有两个参数:第一个是待肯定类型的数据,第二个是指定一个数据类型,判断二者是否一致,返回一个布尔值。
>>> isinstance(123, int) True
4. zip()
zip(ite1[,iter2[...]])
函数接收两个序列,要求它们元素数据相等,返回两个序列元素一一对应的元组(返回的是 zip 对象的内存地址)。
>>> p = {'name': 'rose', 'age': 18, 'gender': 'male'} >>> t = zip(p.keys(), p.values()) >>> list(t) [('name', 'rose'), ('age', 18), ('gender', 'male')] >>> list(zip(['a', 'b', 'c'], [1, 2, 3])) [('a', 1), ('b', 2), ('c', 3)] >>> for i in zip(['a', 'b', 'c'], [1, 2, 3]): ... print(i) ... ('a', 1) ('b', 2) ('c', 3)
5. max()、min()
max(iterable, key, default)
、min()返回一个序列中的最大、小元素。
特性:
>>> max([1, 2, 3]) 3 >>> max(['a', 'b']) 'b' >>> max(['a12', 'a2']) # a 相同,2>1 'a2' # b>a >>> max(['a12', 'b10']) 'b10' >>> age = {'rose': 18, 'tom': 19} # 字典比较默认比较 key >>> max(age) 'tom' >>> max(zip(age.values(), age.keys())) # 既比较大小,又把名字也打印出来 (19, 'tom')
max()还能够指定比较方法:
# 取出 age 比较 >>> people = [ {'name': 'rose', 'age': 18}, {'name': 'lila', 'age': 30}, {'name': 'tom', 'age': 60} ] >>> max(people, key=lambda dic:dic.get('age')) {'name': 'tom', 'age': 60}