从函数对象到名称空间与作用域

mac2022-06-30  87

函数对象

函数(Function)作为程序语言中不可或缺的一部分。

在 Python 中万物皆为对象,函数也不例外,函数作为对象可以赋值给一个变量、可以作为元素添加到集合对象中、可作为参数值传递给其它函数,还可以当做函数的返回值,这些特性就是第一类对象所特有的。

函数拥有对象的三个通用属性:值、id、类型

def pr_Hi(): print('Hello World!') print(id(foo)) # 21301264 print(type(foo)) # <class 'function'> print(foo) # <function pr_Hi at 0x01450810>

函数可以被引用

def pr_Hi(): print('Hello World!') pr_Hi2 = pr_Hi #引用,赋值 print(pr_Hi2) # <function pr_Hi at 0x03020810> print(pr_Hi) #<function pr_Hi at 0x03020810> pr_Hi2() # Hello World!

函数可以放入容器类数据类型

容器对象(list、dict、set等)中可以存放任何对象,函数也可以作存放到容器对象中

def pr_Hi(): print('from pr_Hi') dic={'func':pr_Hi} pr_Hi() # from pr_Hi print(dic['func']) # <function pr_Hi at 0x00BE0810> dic['func']() # from pr_Hi

函数还可以当做参数

def pr_Hi(): print('from pr_Hi') # from pr_Hi def bar(func): ##执行函数 print(func) # <function pr_Hi at 0x014E0810> func() ##调用上面地址的函数 bar(pr_Hi) ##第一步,先调用bar()函数

函数可以作为返回值

def pr_Hi(): print('from pr_Hi') def bar(func): return func f=bar(pr_Hi) print(f) # <function pr_Hi at 0x00CA0810> f() # from pr_Hi

函数还可以嵌套

def f1(): def f2(): print('from f2') return f2 abc = f1() # f1()拿到函数的返回值,函数的返回值是f2, abc就相当于f2 abc() # from f2

匿名函数

python 使用 lambda 来创建匿名函数。

所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。

lambda 只是一个表达式,函数体比 def 简单很多。lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

语法

lambda [arg1 [,arg2,.....argn]]:expression

例如

sum = lambda arg1, arg2: arg1 + arg2 # 调用sum函数 print ("相加后的值为 : ", sum( 10, 20 )) # 30 print ("相加后的值为 : ", sum( 20, 20 )) # 40 ## 这样就是一个逻辑简单的匿名函数了,不过匿名函数一般不这么使用

匿名函数的用法

匿名函数一般和内置函数一起使用,例如:sort,sorted一起使用

lt = [('a', 3000), ('i', 2600), ('o', 15000), ('d', 6500), ('p', 3000)] lt.sort() print(lt) # [('a', 3000), ('d', 6500), ('i', 2600), ('o', 15000), ('p', 3000)] ##这样只能让列表里面的元祖以元祖的第一个元素进行排序 ##所以我们需要自己定义一个规则来进行排序 def abc(i): ##你们千万不要学我,我实在想不出来用什么好,就随便使用了 return i[1] lt = [('a', 3000), ('i', 2600), ('o', 15000), ('d', 6500), ('p', 3000)] lt.sort(key=abc) ## 可以通过他的key来改变它排序的规则 print(lt) # [('i', 2600), ('a', 3000), ('p', 3000), ('d', 6500), ('o', 15000)] ## 发现使用函数想不出函数名这个比较尴尬,还是使用匿名函数好些 lt = [('a', 3000), ('i', 2600), ('o', 15000), ('d', 6500), ('p', 3000)] lt.sort(key=abc) ## 可以通过他的key来改变它排序的规则,这样就可以不用考虑函数名 print(lt) # [('i', 2600), ('a', 3000), ('p', 3000), ('d', 6500), ('o', 15000)]

函数空间与作用域

一扯到函数的嵌套就不由自主的要开始扯函数空间与作用域了。

函数空间:存放名字的地方,准确的说名称空间是存放名字与变量值绑定关系的地方

内置名称空间:python自带的名字,在python解释器启动时产生,存放一些python内置的名字全局名称空间:在执行文件时,存放文件级别定义的名字局部名称空间:在执行文件的过程中,如果调用了函数,则会产生该函数的名称空间,用来存放该函数内定义的名字,该名字在函数调用时生效,调用结束后失效

名称空间的顺序

加载顺序:内置名称空间 --> 全局名称空间 --> 局部名称空间查找顺序:局部名称空间 --> 全局名称空间 --> 内置名称空间

作用域: 产生作用的范围

全局作用域:全局存活,全局有效局部作用域:局部存活,局部有效 x = 1 def f2(): x = 2 # x=2只能在f2中使用 print(x) print(x) # 1 f2() # 2

如果实在要改变全局的变量或者是局部的变量

改全局名称
x = 1 def f1(): global x x = 2 f1() print(x) # 2
改局部名称
x = 0 def f1(): x = 1 def f2(): x = 2 def f3(): nonlocal x #改的是函数正上方的值 x = 3 print('f3',x) # f3 3 f3() print('f2',x) # f2 3 f2() print('f1',x) # f1 1 print(x) # 0 f1()
推荐使用引用类型
lt = [1,2,3] # 作用域关系仅适用不可变数据类型,不适用于可变数据类型 def f1(): lt.append(4) print(lt) # [1, 2, 3] f1() print(lt) # [1, 2, 3, 4]

转载于:https://www.cnblogs.com/Gredae/p/11329301.html

最新回复(0)