函数设计思想
将可能需要反复执行的代码封装为函数,并且在需要该功能的地方进行调用,这样不仅可以实现代码复用,更重要的是可以保证代码的一致性,只需要修改该函数代码,则所有调用均受到影响。
函数形式
def 函数名([参数列表]):
'''注释'''
函数体
注意事项
函数形参不需要声明类型,也不需要指定函数返回值类型,即使该函数不需要接收任何参数,也必须保留一对空的圆括号(括号后面的冒号也不能少),函数体相对于def关键字必须保持一定的空格缩进。Python允许嵌套定义函数。
函数递归调用
函数的递归调用是函数调用的一种特殊情况,函数调用自身,自己再调用自己,......,当某个条件得到满足的时候就不再调用,然后再一层一层的返回,直到该函数第一次调用的位置。
注意:是函数自身调用自身,当某个条件达到要求后,再一层一层返回。
参数传递的序列解包
传递参数时,可以通过在实参序列前加一个星号将其解包,然后传递给多个单变量形参。
>>> def demo(a, b, c):
print(a+b+c)
>>> seq = [1, 2, 3]
>>> demo(*seq)
6
>>> tup = (1, 2, 3)
>>> demo(*tup)
6
如果函数实参是字典,可以在前面加两个星号进行解包,等价于关键参数。
>>> def demo(a, b, c):
print(a+b+c)
>>> dic = {'a':1, 'b':2, 'c':3}
>>> demo(**dic)
6
>>> demo(a=1, b=2, c=3)
6
>>> demo(*dic.values())
6
return语句
return语句用来从一个函数中返回一个值,同时结束函数。对于一下情况,python将认为该函数以return None结束,返回空值:
函数没有return语句;
函数有return语句但是没有执行到;
函数有return但是没有返回任何值。
在调用函数或对象方法时,一定要注意有没有返回值,这决定了该函数或方法的用法。
>>> a_list = [1, 2, 3, 4, 9, 5, 7]
>>> print(sorted(a_list))
[1, 2, 3, 4, 5, 7, 9]
>>> print(a_list)
[1, 2, 3, 4, 9, 5, 7]
>>> print(a_list.sort())
None
>>> print(a_list)
[1, 2, 3, 4, 5, 7, 9]
变量的作用域
变量起作用的代码范围称为变量的作用域,不同作用域内变量名可以相同,互不影响。
局部变量
在函数内部定义的普通变量只在函数内部起作用,称为局部变量。当函数执行结束后,局部变量自动删除,不再可以使用。
局部变量的引用比全局变量速度快,应优先考虑使用
如果局部变量与全局变量具有相同的名字,那么该局部变量会在自己的作用域内隐藏同名的全局变量
全局变量
全局变量可以通过关键字global来定义。这分为两种情况:
1.一个变量已在函数外定义,如果在函数内需要为这个变量赋值,并且要将这个赋值结果反映到函数外,可以在函数内使用global将其声明为全局变量。
2.如果一个变量在函数外没有定义,在函数内部也可以直接将一个变量定义为全局变量,该函数执行后,将增加一个全新的全局变量。
>>> def demo():
global x
x = 3
y = 4
print(x,y)
>>> x = 5
>>> demo()
3 4
>>> x
3
>>> y
NameError: name 'y' is not defined
变量的作用域范围
def scope_test():
def do_local():
spam = "我是局部变量"
def do_nonlocal():
nonlocal spam #这时要求spam必须是已存在的变量
spam = "我不是局部变量,也不是全局变量"
def do_global():
global spam #如果全局作用域内没有spam,就自动新建一个
spam = "我是全局变量"
spam = "原来的值"
do_local()
print("局部变量赋值后:", spam)
do_nonlocal()
print("nonlocal变量赋值后:", spam)
do_global()
print("全局变量赋值后:", spam)
scope_test()
print("全局变量:", spam)
lambda表达式
lambda的一些概括
lambda表达式可以用来声明匿名函数,也就是没有函数名字的临时使用的小函数,尤其适合需要一个函数作为另一个函数参数的场合。也可以定义具名函数。
lambda表达式只可以包含一个表达式,该表达式的计算结果可以看作是函数的返回值,不允许包含复合语句,但在表达式中可以调用其他函数。
lambda表达式范例
>>> f = lambda x, y, z: x+y+z #可以给lambda表达式起名字
>>> f(1,2,3) #像函数一样调用
6
>>> g = lambda x, y=2, z=3: x+y+z #参数默认值
>>> g(1)
6
>>> g(2, z=4, y=5) #关键参数
11
>>> L = [(lambda x: x**2),
(lambda x: x**3),
(lambda x: x**4)]
>>> print(L[0](2),L[1](2),L[2](2))
4 8 16
>>> D = {'f1':(lambda:2+3),
'f2':(lambda:2*3),
'f3':(lambda:2**3)}
>>> print(D['f1'](), D['f2'](), D['f3']())
5 6 8
>>> L = [1,2,3,4,5]
>>> print(list(map(lambda x: x+10, L))) #模拟向量运算
[11, 12, 13, 14, 15]
>>> L
[1, 2, 3, 4, 5]
>>> data = list(range(20)) #创建列表
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> import random
>>> random.shuffle(data) #打乱顺序
>>> data
[4, 3, 11, 13, 12, 15, 9, 2, 10, 6, 19, 18, 14, 8, 0, 7, 5, 17, 1, 16]
>>> data.sort(key=lambda x: x) #和不指定规则效果一样
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> data.sort(key=lambda x: len(str(x))) #按转换成字符串以后的长度排序
>>> data
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> data.sort(key=lambda x: len(str(x)), reverse=True) #降序排序
>>> data
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#注意:在这里,0-9的长度是一样的,10-19的长度是一样的。故10-19排前面,0-9排后面。
一些函数设计案例
逆序
编写函数,接收包含20个整数的列表lst和一个整数k作为参数,返回新列表。处理规则为:将列表lst中下标k之前的元素逆序,下标k之后的元素逆序,然后将整个列表lst中的所有元素再逆序。
def demo(lst,k):
x = lst[:k]
x.reverse()
y = lst[k:]
y.reverse()
r = x+y
r.reverse()
return r
lst = list(range(1,21))
print(demo(lst,5))
斐波那契数列
编写函数,接收整数参数t,返回斐波那契数列中大于t的第一个数。
def demo(t):
a, b = 1, 1
while b