第五章 函数
一,定义函数
def 函数名([参数列表]):
"""注释"""
函数体
*紧跟着的"""里面可以写关于函数的说明,后续可以用>>>help(函数名)查看注释
二,形参与实参
形参和实参的概念基本和C语言一样,但是当参数传递像列表,字典这样的可变对象时,函数中对可变对象参数的在原处的修改能够影响调用者(即改变实参)
例:
>>>def modify(d):
... d['eggs']=3
...
>>>a={'spam':1}
>>>modify(a)
>>>a
{'spam':1,'eggs':3}
如果想要避免改变可变对象,可以采用切片操作之类拷贝可变对象再传入函数
三,参数类型
1.普通参数
2.默认参数
默认参数写在参数列表的最右边,右边只能也是默认参数。可以不对默认值参数进行赋值,也可以赋值
使用"空列表"作为函数的默认值参数是危险的,不要这么做使用{},[]这样的"空"可变对象作为默认参数,并在函数内部原地改变它们时,你对它的修改会保留到这个函数第二次被调用的时候,第二次会保留到第三次,以此类推。
例:
>>>def my_append(item,my_list=[])
... my_list.append(item)
... return my_list
>>>my_append(1)
[1]
>>>my_append(2)
[1,2]
之所以会出现这样的错误,是因为默认值参数只被生成一次,只在def函数定义语句被执行的时候被生成一次。def函数定义语句在函数定义后被解释器执行,在内存中生成函数对象,结果之一就是默认值参数被赋值为空,二这个过程只做一次。
解决方法:
一,如果是对可变对象的赋值操作(生成了新对象)就没有关系,如例子中的data.append(1)会出错,换为data=data+[1]就没有问题
二,用如下格式
>>>def my_append(item,my_list=None):
... if my_list is None
... my_list=[]
... my_list.append(item)
... return my_list
>>>
也可以利用这种性质
def calculate(a,b,c,memo={}):
a,b,c是计算所需要的参数,memo是一个空字典
try:
value=memo[a,b,c]
以a,b,c三个元素所组成的元组为键值,看memo的缓存有没有a,b,c所对应的值(a,b,c这三个参数有没有被算过),算过就能取出a,b,c所对应的value。若无这个键产生key error说明未算过h。eavy_caculation并
存储value进memo
except keyError:
value=heavy_calculation(a,b,c)
memo[a,b,c]=value
return value
3.关键参数(实参)
*减少错误,指定赋值
4.可变长度参数(形参)
*parameter 可以传递任意多个实参 **parameter期待字典定义的形式
注:例子里 for item in p.items()是为了输出字典的键值对,a=1,b=2,c=3的输入方式是为了构造字典
四,函数调用时的参数解包
为含有多个形参的函数传递实参时,可使用列表,元组,字典,集合以及其它可迭代对象作为实参,并在实参名*,Python解释器将自动进行解包将序列中的元素传递给多个形参
*不要混淆函数定义中的可变参数和函数调用时的参数解包,一个出现在函数定义中,一个出现在函数调用中(必考)
*如果使用字典对象作为实参,则默认使用字典的键
*’**'会以键值对的形式解包一个字典,如
>>>def my_func(spam,ham,eggs):
... print spam,ham,eggs
>>>args={'spam':1,'ham':2,eggs:3}
>>>my_func(**argc)
1 2 3
把1赋给spam的参数,2赋给ham的参数,3赋给eggs
>>>args={'a':1,'b':2,'c':3}
>>>my_func(**argc)
会报错,因为这个相当于告诉python把1赋给名为'a'的参数,而函数定义里没
参数'a'
五,return语句
return语句缺失时,默认以return None结尾
六,变量的作用域
global关键字的可以变函数内局部变量为全局变量
如果在函数内任意位置有为变量赋新值的操作,该变量即被认为是局部变量
例子:
>>>x=99
>>>def func():
... print x
... x=100
... print x
...
>>>x
99
>>>func() 报错,因为x有赋值操作被认为是局部变量,而print x使用时x没赋值就被引用
在函数内若只引用某个变量的值而没有为其赋值,该变量为全局变量
例子:
>>>x=99
>>>def func()
... print x
...
>>>x
99
>>>func()
99
在函数内要为变量赋新值的操作又不想被认为是局部变量就要用 global 关键字
例子:
>>>x=99
>>>def func():
... global x
... print x
... x=100
... print x
...
>>>x
99
>>>func()
99
100
>>>x
100
在函数内部直接将一个变量声明为全局变量,而在函数外没有声明,在调用这个函数之后该变量增加为新的全局变量
六,python变量的作用域LGB原则(必考)
如果python解释器见到一个变量它不知道变量在哪里定义,它的查找顺序就是Local(
function内部)–Global–Built-in。都找不到就报错
七,lambda表达式(一般作为参数传输给其他函数)
例:f=lambda x,y,z:x+y+z
*map(function,sequence),将单参数函数function依次作用到序列sequence的每一元素上。例子中直接用lambda函数传入function(例子:map(lambda x:x+5,range(5)))
lambda表达式内部可以调用其他函数
例:map(lambda x:do square(x),my_list)
lambda表达式在list.sort()方法和内置函数sorted中也经常被使用(具体见PPT,考试不会考这么细,只会考sort()和sorted有没有返回值)
*下为常与lambda搭配使用的Built-in Functions
map
python2返回一个列表,python3返回可迭代对象,map也可以作用于多个序列:此时,map期待一个N个参数的函数用于N个序列(如:map(pow,[1,2,3],[2,3,4]))
reduce
在python3中被取消,必须要from function import reduce才能使用。将一个接受两个参数的函数以累积的方式从左到右依次作用到一个序列或迭代器对象的所有元素上(如:reduce(lambda x,y:x+y,range(10))得到45)
filter
自己回去看,重点是map和reduce以及lambda的语法
*番外:
多态的概念(了解概念即可,看PPT)
LE(嵌套函数Enclosing function locals的本地作用域)GB原则
(两个例子和Closure amd Factory Function自己回去看PPT)
嵌套函数的作用:
1.不让外部调用内部的这个函数
2.用于实现工厂函数(工厂函数的return返回一个函数名,工厂函数就是创造函数,返回新的函数的函数)
查找顺序总结(重点必考):
1.对一个变量x的引用首先会在本地(当前函数)作用域内查找变量x
2.*之后会在代码语法上嵌套了这个函数的函数,也就是外层函数的本地作用域中查找
3.查找全局作用域
4.最后在内置作用域内查找
即首先是本地,之后是外层函数内(如果有外层函数的话),之后是全局,最后是内置
nonlocal(不考,自己看)
编辑于2020-4-10 19:09