首页 > 技术文章 > 【python】 函数 进阶

luwenqing 2019-01-24 14:29 原文

函数进阶

1、函数命名空间和作用域

命名空间一共分为三种:

  全局命名空间

  局部命名空间

  内置命名空间

*内置命名空间中存放了python解释器为我们提供的名字:input , print , str , list , tuple... 

三种命名空间之间的加载与取值顺序:

加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

取值顺序:

  在局部调用:局部命名空间->全局命名空间->内置命名空间

  在全局调用:全局命名空间->内置命名空间

综上所述,在找寻变量时,从小范围,一层一层到大范围去找寻。

作用域

作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。

全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

局部作用域:局部名称空间,只能在局部范围生效

globals和locals方法:

global 关键字:

  1、声明全局变量;

  2、在局部作用域对全局作用域的全局变量进行修改,只适用于字符串和数字

## 变量为字符串或数字,需要global声明变量
2 b = 1 3 def func(): 4 global b ## 将局部变量 b 申明成全局变量 5 b = 13 6 return b 7 8 print(func())
运行结果:13

## 变量为非字符串和数字,可以直接修改全局变量
12 b = [1,2,3] 13 def func(): 14 b = [4,5,6] 15 return b 16 17 print(func())

运行结果:
[4,5,6]

 

nonlocal 关键字:

  1、不能修改全局变量;

  2、在局部作用域中,对父级作用域(或者更外层的作用域非全局作用域)的变量进行引用和修改,此层及以下的变量全部发生改变。

 

 1 b = 1                     ## 全局变量
 2 def func1():
 3     b = 2
 4     print(b)              ## b = 2
 5     def func2():
 6         nonlocal b        ## 引用上一级的变量 b
 7         print(b)          ## b = 2
 8         def func3():
 9             print(b)      ## b = 2
10 
11 
12         func3()
13     func2()
14 func1()
15 print(b)

运行结果:

2
2
2
1

 

2、函数名 === 第一类对象

 1) 函数名的内存地址

 3 def func():
 4     print(11)
 5 print(func)          ## <function func at 0x0000000002FFC158>
6 print(id(func)) ## 50315608 函数的内存地址
运行结果:

<function func at 0x0000000002FFC158>
50315608
2) 函数名赋值给其他变量 11 def func(): 12 ## 将函数名func赋值给func1 13 print(11) 14 func1 = func 15 func1()
运行结果:

11
3) 函数名可以当做容器内的元素(循环执行函数) 20 def func1(): 21 print(11) 22 def func2(): 23 print(22) 24 def func3(): 25 print(33) 26 def func4(): 27 print(44) 28 list = [func1,func2,func3,func4] 29 for i in list: 30 i()
运行结果:
11
22
33
44 4) 函数名可以当做函数的参数 37 def func1(): 38 print(111) 39 def func2(a): 40 pass 41 func2(func1())
运行结果:
111 5) 函数名可以当做函数的返回值 46 def func1(): 47 print(111) 48 def func2(a): 49 return a 50 func2(func1())
运行结果:
111

 

3、闭包


闭包:内层函数对外层函数(非全局)的变量的引用 1)闭包函数 5 a = 1 6 def func1(): 7 b = 2 8 def func2(): 9 c = b ### 内层函数引用非全局的外层函数变量,是闭包函数 10 return c 11 ret = func2() 12 print(ret) 13 print(func2.__closure__) 14 func1()
运行结果:
2
(<cell at 0x0000000002D87498: int object at 0x000000001D62EC90>,)

2)非闭包函数 18 a = 1 19 def func1(): 20 b = 2 21 def func2(): 22 print(a) ### 内存函数引用全局变量,不是闭包函数 23 func2() 24 print(func2.__closure__) 25 func1()
运行结果:
1
None

3)检测是否为闭包函数 29 def func1(x): 30 def func2(): ### func2 为闭包函数 31 return x 32 ret = func2() 33 print(ret) 34 print(func2.__closure__) ### 检测函数是否是闭包函数(返回cell就是闭包函数,返回none则不是闭包) 35 func1(1) 运行结果:
1
(<cell at 0x0000000002BF7498: int object at 0x000000001D5CEC70>,)

4)闭包函数的应用 40 def wrapper(): 41 money = 1000 42 def func(): 43 name = "eva" 44 def inner(): 45 print(name,money) 46 return inner() 47 return func() 48 f = wrapper()
运行结果:
eva 1000
5)闭包的用处:若内存函数是个闭包,python内部有个机制, 遇到闭包,会在内存中开启一个内存空间,不会随着函数的结束而关闭 54 from urllib.request import urlopen 55 56 def pachong(url): 57 content = urlopen(url).read() 58 def get(): ### 通过闭包函数的特性节俭资源 59 with open("爬虫","ab") as f: 60 f.write(content) 61 return get ### 执行内层函数 62 pachong("https://www.cnblogs.com/")()

6)拓展 1、执行内层函数的两种方式:
  
1)返回内层函数的函数值 70 def wrapper(): 71 def inner(): 72 print(66) 73 return inner 74 wrapper()() # 执行顺序:先调用函数wrapper(),返回 inner,再调用函数inner(),打印内部函数inner()
运行结果:
66
  2)直接调用内部函数 82 def wrapper(): 83 def inner(): 84 print(66) 85 inner() 86 wrapper()
运行结果:
66

 

推荐阅读