一、概述
函数, 就是用一些语句组织起来实现一组特定的功能, 用来重复调用.
函数的作用及意义:最大化的重用代码和最小化的代码冗余以及对流程的分解.
Python中有哪些函数:
- 内建的函数
- 第三方模块中的函数
- 自定义的函数
关于内置函数, 参考:
http://python.usyiyi.cn/python_278/library/functions.html
http://www.cnblogs.com/huangweimin/p/5619633.html
二、自定义函数
- def语句声明, 函数也是一个对象, 函数名指向这个函数对象.
- 函数可以传参, 位置参数、默认参数、收集参数 (形式参数、实际参数)
- 函数用return将调用的的结果对象返回, 并且代表函数的结束
- 自定义的函数不要和内置的对象冲突
- 函数没有被调用不会执行
- 理解作用域和命名空间, LEGB原则
//牢记: 函数也是一个对象,函数名只不过是指向函数对象的变量名
1、普通函数
def sayHi(): # 声明函数 print 'Hello python' # 函数体 print sayHi sayHi() # 执行函数 结果: <function sayHi at 0x00000000025209E8> #函 数就是一对象,返回在内存中的地址 Hello python//解释器遇到def函数语句,在内置中创建函数对象,函数名指向这个函数对象
2、函数传参 (形式参数、实际参数)
函数可以传参数,关键字参数、默认参数、收集参数
1、关键字参数
def func(name,age): # 定义形式参数 print 'I am',name,'age',age func('zhang', 25) # 传参,实际参数,对应关系 结果: I am zhang age 25
- 形式参数可以说就是摆设,需要传实际的参数进去,它们是对应的关系
- 先在内存中创建'zhang',25,然后将形式参数name,age分别指向它们
- 如果不传参数会抛出异常TypeError
- 函数的参数不是变量, 而是一种传值引用
2、默认参数
def func(name,age=19): # age是默认参数 print 'I am',name,'age',age func('zhang') func('li',age=21) # 直接修改默认参数 func(name='wang',21) # 同理 结果: I am zhang age 19 I am li age 21 I am wang age 21
- 默认参数相当于一个初始的参数,不能是不可变的对象
- 如果不传默认参数,则使用默认参数,如果传相当于覆盖修改
- 默认参数一定要放到最后面,可以有多个
3、收集参数 *args、**kwargs
number = (1,2,3,4,5) def func(*args): # 定义收集参数 print args func() # 不传参数调用 func(1,2) # 传参 func('abcdefg') # 传字符串参数 func('zhang','li','zhao') # func(number) # 传一个序列 func(*number) # 传*序列 结果: () # 返回一个空(),说明*args的方式是构造一元组来装传过来的参数 (1, 2) ('abcdefg',) ('zhang', 'li', 'zhao') ((1, 2, 3, 4, 5),) (1, 2, 3, 4, 5)
- 说明*args构造的一个空tuple来装传过来的参数,如果要传一个列表或者元组需要在前面添加*抵消掉原来的tuple
dic = {"key1":"value1","key2":"value2"} def func(**kwargs): print kwargs func() # 返回空{},说明**kwargs构造的是一个空的{}来装参数 func(key1='value1',key2='value2') func(**dic) 结果: {} {'key2': 'value2', 'key1': 'value1'} {'key2': 'value2', 'key1': 'value1'}
- 说明**kwargs是用空{}来装参数,它只接受key=value形式的传参,否则会抛出错误TypeError,返回一个字典的形式(key不需要加引号)
- 如果要传一个字典,需要在前面添加**
4、收集参数(就是*args、**kwargs的混用)
t1= (1,2,3) dic = {'key1':'value1','key2':'value2'} def func(*args,**kwagrs): print args,kwagrs func() func(1,2,3) func(key1='value1',key2='value2') func(1,2,3,key1='value1',key2='value2') func(*t1,**dic) 结果: () {} (1, 2, 3) {} () {'key2': 'value2', 'key1': 'value1'} (1, 2, 3) {'key2': 'value2', 'key1': 'value1'} (1, 2, 3) {'key2': 'value2', 'key1': 'value1'}
- 收集参数*args、**kwargs可以混用,比较灵活,注意它们也有对应的关系,不能反着传
3、函数的返回值
- 函数的返回值用return, 默认是None
- 函数遇到了return就不会执行后面的语句,代表函数的结束
- 函数只能return一种对象, 其实就是个tuple
1、函数执行遇到了return就不会往下面执行
def adds(x,y): return x+y print 'done' #不会执行 reslut = adds(10, 20) print reslut 结果: 302、return与print
def adds(x,y): b = x+y print b reslut = adds(10, 20) print reslut 结果: 30 None # 没有retrun,默认返回None def adds(x,y): b = x+y return b reslut = adds(10, 20) print reslut 结果: 30//函数的return应该使用return而不是print
3、函数只能return一种对象,这也是函数的限制
>>> def adds(): ... return 1,{} ... >>> adds() (1, {})//在adds()函数中,用return貌似返回int和dict两个对象,但是实际得到的是一个元组对象,说明return构造的是一个tuple对象返回调用的结果
4、函数的作用域
函数有自己的命名空间,即作用域:
- 函数的内部变量不能被外部引用,除非global声明
- 函数外部的变量能够被函数引用
- LEGB原则,本地变量---上层函数---全局---内置
1、函数内的变量不能被外部引用,除非global声明
def func(): x = 10 print x func() 10 print x NameError: name 'x' is not defined #异常如果global声明则可以调用:
def func(): global x x = 10 print x func() 10 #结果 print x #可以引用 102、全局与局部如冲突,局部优先,只作用在函数里面
a = 11 def fun1(): a = 10 print a fun1() print a 结果: 10 11 #注意并没有修改全局的变量a如果添加global声明,则修改全局:
a = 11 def fun1(): global a a = 10 print a fun1() print a 结果: 10 103、内层函数优先
def func1(): a = 10 def func2(): a = 11 #先找内层的a print a func2() func1() 结果: 114、内层函数找不到再找外层函数
a = 1 def func3(): a = 10 def func4(): print a #内层函数找不到再找外层函数 func4() func3()5、内层、外层函数都没有,找全局的
a = 1 def func3(): def func4(): print a #内层、外层都没有 func4() func3()
三、lambda、map、filter、reduce
1、lambda
匿名函数就是没有名字的函数,lambda是匿名函数,可以实现简单的函数功能但作用有限
特点:
- 只是一种表达式函数,简单实现函数的功能
- 不需要函数名,本身也没有函数名,好处是有时候函数命名也不好管理
- 自动返回结果returen
- 同样可以传参数,收集参数、关键字参数、默认参数
用法:
"lambda" [parameter_list]: expression parameter_list: 参数列表 expression: 表达式
1、简单的def函数可以用lambda表示
def func1(a,b): return a + b print func1(10,20) 结果: 30 def func2(a): return a * 10 print func2(10) 结果: 100用lambda表达式可以写成:
restult1 = lambda x,y: x + y #x,y是形式参数 restult2 = lambda x: x * 10 #x是形式参数 print restult1(10,20) 30 print restult2(10) 100
- 和函数一样,x,y可以看成是一个形式参数,可以传参
2、传默认参数、动态参数(*args,**kwagrs),默认参数也要放到最后面
func1 = lambda arg2,arg1=10:arg2+arg1 #arg1是默认参数,放到后面 print func1(20) 30 print func1(20,20) 40动态参数*args
func1 = lambda *args:args print func1(1,2,3,4) #传数字 print func1('abcdefg') #传字符串 print func1((1,2,3,4)) #传tuple print func1(*(1,2,3,4)) #传*tuple 结果: (1, 2, 3, 4) ('abcdefg',) ((1, 2, 3, 4),) (1, 2, 3, 4)传动态参数**kwargs
func2 = lambda **kwargs:kwargs print func2() print func2(key1="value1",key2="value2") print func2(**{"key1":"value1","key2":"value2"}) 结果: {} {'key2': 'value2', 'key1': 'value1'} {'key2': 'value2', 'key1': 'value1'}
- lambda函数传参和普通函数是一样的,*args、**kwargs分别构造的是空元组、空字典来装参数
3、def 声明函数是将函数名指向函数对象,而lamdba不是
def func1(): pass print func1 func2 = lambda a:a+1 print func2 结果: <function <lambda> at 0x00000000025C09E8> #始终返回的是lambda对象 <function func1 at 0x00000000025C0A58>
2、map
接收两个参数,函数和可迭代的对象,将function应用于iterable对象的每一个元素,返回结果的列表
用法: map(function, sequence[, sequence, ...]) -> list (返回list)
li = [11,22,33,44,55,66,77]1、给li列表中所有的元素加10返回一新的list
def func(args): return args + 10 reslut = map(func,li) #map接收两个参数,一个函数,一个是列表,将里面中的每个元素作为参数传到func函数中最终得出结果 print reslut[21, 32, 43, 54, 65, 76, 87]也可以用lambda表示:
result = map(lambda a:a+10,li) print result [21, 32, 43, 54, 65, 76, 87]2、map接收多个序列
li = [11,22,33,44,55,66,77] li2 = [22,33,44,55,66,77,88] result = map(lambda a,b:a+b,li,li2) print result [33, 55, 77, 99, 121, 143, 165]
- map函数遍历序列做为参数传给一个函数经过处理,返回一个新的列表。序列可以有个,可以是list和tuple
- map是高阶函数,一个函数作为参数传给另一函数
3、filter
对于序列中的元素进行筛选,最终获取符合条件的序列
用法: filter(function or None, sequence)
li = [11,23,18,44,55,21]1、filter函数从li列表中每取一个元素应用到func,进行筛选,得出符合条件的元素
def func(*args): for i in args: if i > 22: return i reslut = filter(func, li) #从li中每取一个元素作为参数传给func,返回符合条件的元素. print reslut [23, 44, 55]等同于:
li = [11,23,18,44,55,21] reslut = filter(lambda arg: arg > 22,li) print reslut [23, 44, 55]
- 如果li是字符串返回的也是字符串、如果是元组返回的也是元组
4、reduce
归纳的意思,接受两个参数: 函数、序列型对象,从序列性的对象中拿出两个元素作作为参数传给函数,累积操作。返回一个值
用法: reduce(function, sequence[, initial]) -> value
- initial: 初始值
reduce(...) reduce(function, sequence[, initial]) -> value Apply a function of two arguments cumulatively to the items of a sequence, from left to right, so as to reduce the sequence to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). If initial is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty.reduce
计算1*2*3*4*5
def func(x,y): return x * y reslut = reduce(func, [1,2,3,4,5]) print reslut 120 等同于: reslut1 = reduce(lambda x,y:x*y,[1,2,3,4,5]) print reslut1 120也可以指定初始值initial
reslut1 = reduce(lambda x,y:x*y,[2,2,3,4,5],10) print reslut1 2400PS: 所以reduce函数就是从序列中拿出两个元素作用到函数中进行累积操作
总结:
- 函数的种类,内置函数、第三方模块函数、自定义函数
- def函数定义,函数名是函数对象的指向, 不要和内置函数冲突
- 函数可以传参, 关键字、默认、收集参数,默认参数要放到最后面
- 参数是函数的入口,return是函数的出口
- 函数的return只能返回一种对象,就是tuple
- 注意函数的作用域,全局与局部变量的关系,尽量不用使用全局变量
- 函数调用应该用return而不是用print,return代表函数的结束,函数执行完后内部对象会被回收
- 一个函数尽量只做一件事情