Python 函数详解

来源:互联网 发布:休闲单机游戏推荐知乎 编辑:程序博客网 时间:2024/06/05 08:32

作用域

全局变量&局部变量

全局变量和局部变量都是在讨论无参数的函数,不要把全局变量和局部变量与函数的参数混淆了。
1.1 函数会在函数域中找变量(局部变量),如果函数内部没有定义该变量,则会在全局中寻找变量(全局变量)

a=100def test1():    print(a) # 输出结果100,函数域里没有a,所以去全局寻找def test2():    a=200    print(a) # 输出结果为200,函数域里有a,所以取函数域里面的值

1.2 当一个函数使用了全局变量时,就不能再在函数域中修改同名变量,因为这个操作是在修改全局变量

a=100def test1():    print(a)     a=200 # 此处不可以修改全局变量    print(a) test1()UnboundLocalError: local variable 'a' referenced before assignment

如果想要修改全局变量,要先用global声明

a=100def test1():    global a    print(a)     a=200 # 这里变成修改全局变量    print(a) # 输出结果为200,

1.3 之所以不能修改全局变量,是因为局部作用域不能修改全局变量的指向,正是因为这个原因,所以对列表等可变的类型,可以不用声明就可以修改全局,因为没有更改其指向,而是修改了内容。

a=[1]def test1():    a.append(1)    print(a)

Python 使用 LEGB 的顺序来查找一个符号对应的对象
locals -> enclosing function -> globals -> builtins
1. locals,当前所在函数、模块
2. enclosing,外部嵌套函数的命名空间(闭包中常见)
3. globals,全局变量,函数定义所在模块的命名空间
4. builtins,内建模块的命名空间

参数(args)

形参和实参

形参是函数括号里面的参数(定义的时候),实参是传递给形参的值(调用的时候)

def test(a, b):# ab是形参    return a+btest(a=1,b=2)# 1,2分别是a,b的实参

默认参数

可以给参数默认值

def test(a=1,b):# 如果调用参数时不给a赋值,则默认a=1

不定长参数

不定长参数,可以用循环取出

*args 单星号参数

*单星号参数实质是传入一个元组

In [1]: def name(*args):   ...:     print(args)In [2]: name(1,2,3)(1, 2, 3)

**kwargs 双星号参数

双星号参数实质是字典,表示带变量名的参数

In [1]: def test(**kwargs):   ...:     for key, value in kwargs.items():   ...:         print(key+"="+value)In [2]: name(a="1",b="2")a=1b=2

Python中函数参数是引用传递(注意不是值传递)。对于不可变类型,因变量不能修改,所以运算不会影响到变量自身;而对于可变类型来说,则相反

返回值(return)

可以使用list tuple dict 或者直接用,将多个结果同时返回(本质是tuple)

其他

匿名函数:

lambda [arg1 [,arg2,…..argn]]:expression
冒号:后面相当于return返回

函数作为参数

当函数作为参数时,是把函数的引用传入到了函数里
def name(a,b,func)

字符串转函数

字符串转表达式
eval() 结合eval input可以给python传入function

闭包

闭包就是指内层函数,以及外部函数的变量

In [1]: def line(a, b): # 生成了一个确定了ab的线性函数,结果只需要给x值就可以判断y值   ...:     def line(x):   ...:         return a*x + b   ...:     return line # 返回值为闭包,就是内层函数In [2]: line1 = line(1, 1) # 用line1接受a=1,b=1的闭包函数   ...: line2 = line(-1, 1) # 用line2接收a=1,b=-1的闭包函数In [3]: line1(1)Out[3]: 2In [4]: line2(1)Out[4]: 0

由于闭包函数引用了外部函数的变量,所以不能及时释放外部函数的内存

装饰器

开放(对扩展开发)封闭原则 (已实现的功能代码块,不能修改)
装饰器: 先装饰(从下往上),后调用(从上往下)
简单的来讲,就是被装饰的函数会被转换为装饰函数闭包的函数。

In [1]: def Bold(fn):   ...:     def wrapped():# 闭包,这个函数的作用就是给原来的函数增加一些功能,   ...:         return "<b>" + fn() + "</b>"   ...:     return wrapped# 返回的是闭包,然后再把这个新的函数的名字赋值成原来的函数名   ...:    ...: @Bold   ...: def test():   ...:     return "python"In [2]: test()Out[2]: '<b>python</b>'

等价于

In [1]: def wrapped(test):# 参数以后会是一个函数   ...:     return "<b>" + test() + "</b>" # 参数实际上是一个函数   ...:    ...: def test():   ...:     return "python"# 从这里看出,装饰器最外面的函数只是为了最后函数更改名称的方便,就是把wrapped()名字改成过了test()名字In [2]: wrapped(test)Out[2]: '<b>python</b>'
原创粉丝点击