函数:由语句块(若干语句组成),函数名称,参数构成,是组织代码的最小单元,用来完成某种功能;
函数的作用:封装代码,复用,减少冗余代码,使代码更加简洁美观,可读性更高,易懂;
函数的定义: def 函数名(参数列表): 函数体(代码块) [return 返回值] def add(x,y): result = x+y return result out = add(4,5)
print(out)
add是函数名,即标识符,add()调用函数;
python的函数如果过没有指定return语句,默认返回值是None;
return语句不一定是函数块的最后一条语句,一个函数可以有多条return语句,但是只有一条会执行,函数执行了return语句以后,后面的语句块就不会执行了;
上面函数定义中的参数x,y只是形式参数,函数调用是的4,5才是实际参数;
函数是一个可调用对象,canllable()判断是否为可调用对象,返回一个布尔值;
函数参数:
参数调用时传入的参数要和定义时参数的个数相匹配(可变参数除外);
参数列表一般顺序是:普通参数,缺省参数,可变位置参数,keyword-only参数,可变关键字参数;
位置参数:
定义def add(x,y,z):
调用add(1,2,3)
实参和形参一一对应,数量必须相同;
关键字参数:
定义def add(x,y,z):
调用add(x=1,y=2,z=3)
关键字传参时,x,y,z顺序可以和形参顺序不同,参数个数必须相同;
位置参数和关键字参数混用是,位置参数必须放在关键字参数之前传入;
可变参数:
定义def add(*args):
调用add(3,6,9)
可变位置参数一般用*args表示,可变位置参数收集到的实参整合成一个tuple;
定义def add(**kwargs):
调用add(a=3,b=6,c=9)
可变关键字参数一般用**kwargs表示,可变关键字参数收集到的实参整合成一个dict;
参数解构:
def add(x, y): return x+y add(*(4,5)) add(*[4,5]) add(*{4,6}) d = {'x': 5, 'y': 6} add(**d) add(**{'a': 5, 'b': 6})
非字典类型使用*,字典类型使用**;
解构出的元素数目要和参数数目和类型相匹配;
函数参数默认值:
定义函数的时候给参数一个默认值:
def login(host='127.0.0.1',port='8080',username='LPL',password='s7win'):
print('{}:{}@{}/{}'.format(host, port, username, password))
login()
作用:参数默认值可以在为未传入足够实参的时候,对给定的参数取默认值;参数非常多的时候,一些不需要用户经常输入或修改的参数,简化函数调用;
函数作用域***
全局作用域:在整个程序运行环境中可见;
全局变量global(能不用则不用)
x = 2 def foo(): global x x += 1 return x foo() print(foo())
使用global关键字,将函数foo内的x变量声明为外部全局作用域中定义的x变量,全局作用域中必须有定义x变量,不然会抛异常;
局部作用域:在函数内部可见,局部变量使用范围不能超过其所在的局部作用域;
在嵌套函数中,外层局部作用域中的变量在内层局部作用域中是可见的,内层局部作用域中的变量在外层局部变量中是不可见的,内层局部作用域中如果有和外层局部作用域中相同的变量,相当于在内部重新定义一个新的变量,和外层局部作用域无关;
def outer1(): o = 65 def inner(): print("inner {}".format(o)) print(chr(o)) print("outer {}".format(o)) inner() outer1() def outer2(): o = 65 def inner(): o = 97 print("inner {}".format(o)) print("chr(o)") print("outer{}".format(o)) inner() outer2()
闭包*
出现在嵌套函数中,内层函数引用到外层函数的自由变量就是闭包;
自由变量:未在本地作用域中定义的变量,不能是全局作用域变量;
def counter(): c = [0] def inc(): c [0] += 1 return c[0] return inc() foo = counter() print(foo,foo) c = 100 print(foo) print(c) 执行结果: 1 1 1 100
使用nonlocal关键字,将变量标记为不在本地作用域定义,而在某上层的局部作用域中定义的变量(不能是在全局作用域中定义的变量);
def counter(): c = 0 def inc(): nonlocal c c += 1 return c return inc() foo = counter() print(foo)
默认作用域:
python函数参数的默认值放在了属性中,这个属性就伴随这个函数对象的整个生命周期(__defaults__使用元组保存默认值,__kwdefaults__使用字典保存所有的keyword-only默认值);
def foo(xyz=[], u='abc', z=123): xyz.append(1) return xyz print(foo(), id(foo)) print(foo.__defaults__) print(foo(), id(foo)) print(foo.__defaults__) 执行结果: [1] 30359064 ([1], 'abc', 123) [1, 1] 30359064 ([1, 1], 'abc', 123) #函数对象没有变,这里xyz=[]是个引用类型,所以__defaults__默认值会改变; def foo(xyz=[], u='abc', z=123): xyz = xyz[:] xyz.append(1) print(xyz) foo() print(foo.__defaults__) foo() print(foo.__defaults__) foo([10]) print(foo.__defaults__) foo([10,5]) print(foo.__defaults__) 执行结果:[1] ([], 'abc', 123) [1] ([], 'abc', 123) [10, 1] ([], 'abc', 123) [10, 5, 1] ([], 'abc', 123) #函数体内,xyz=xyz[:]传入参数或者默认参数的cp,不能修改__defaults__默认值; def foo(xyz=None, u='abc', z=123): if xyz is None: xyz = [] xyz.append(1) print(xyz) foo() print(foo.__defaults__) foo() print(foo.__defaults__) foo([10]) print(foo.__defaults__) foo([10,5]) print(foo.__defaults__) 执行结果: [1] (None, 'abc', 123) [1] (None, 'abc', 123) [10, 1] (None, 'abc', 123) [10, 5, 1] (None, 'abc', 123) #使用不可变类型默认值,如果使用缺省值None就创建一个列表,如果传入一个列表,就修改这个列表;