1、块级作用域

想想此时运行下面的程序会有输出吗?执行会成功吗?

1
2
3
4
5
6
7
8
9
10
11
12
#块级作用域
 
if 1 == 1:
    name = "lzl"
 
print(name)
 
 
for in range(10):
    age = i
 
print(age)

我们先看下执行结果

1
2
3
4
5
C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/main.py
lzl
9
 
Process finished with exit code 0

代码执行成功,没有问题;在Java/C#中,执行上面的代码会提示name,age没有定义,而在Python中可以执行成功,这是因为在Python中是没有块级作用域的,代码块里的变量,外部可以调用,所以可运行成功;  

2、局部作用域

回顾之前学过的知识,我们学函数的时候,函数是个单独的作用域,Python中没有块级作用域,但是有局部作用域;看看下面的代码

1
2
3
4
5
6
#局部作用域
 
def  func():
    name = "lzl"
 
print(name)

运行这段代码,想想会不会有输出?

1
2
3
4
Traceback (most recent call last):
  File "C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/main.py", line 23in <module>
    print(name)
NameError: name 'name' is not defined

运行报错,我相信这个大家都能理解,name变量只在func()函数内部中生效,所以在全局中是没法调用的;对上面代码做个简单调整,再看看结果如何?

1
2
3
4
5
6
7
#局部作用域
 
def  func():
    name = "lzl"
 
func()          #执行函数
print(name)

对之前的代码添加了一句代码,在变量name打印之前,执行了一下函数,此时打印会不会有变化?

1
2
3
4
Traceback (most recent call last):
  File "C:/Users/L/PycharmProjects/s14/preview/Day8/作用域/main.py", line 23in <module>
    print(name)
NameError: name 'name' is not defined

执行依然报错,还是回到刚才那句话:即使执行了一下函数,name的作用域也只是在函数内部,外部依然无法进行调用;把前两个知识点记住,接下来要开始放大招了

3、作用域链

对函数做下调整,看看下面的代码执行结果如何?

1
2
3
4
5
6
7
8
9
10
#作用域链
 
name = "lzl"
def f1():
    name = "Eric"
    def f2():
        name = "Snor"
        print(name)
    f2()
f1()

学过函数,肯定知道最后f1()执行完会输出Snor;我们先记住一个概念,Python中有作用域链,变量会由内到外找,先去自己作用域去找,自己没有再去上级去找,直到找不到报错

4、终极版作用域

好,铺垫了够了,终极版的来了~~

1
2
3
4
5
6
7
8
9
10
11
12
#终极版作用域
 
name = "lzl"
 
def f1():
    print(name)
 
def f2():
    name = "eric"
    f1()
 
f2()

想想最后f2()执行结果是打印“lzl”呢,还是打印“eric”?记住自己的答案,现在先不把答案贴出来,先看看下面这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#终极版作用域
 
name = "lzl"
 
def f1():
    print(name)
 
def f2():
    name = "eric"
    return f1
 
ret = f2()
ret()
 
#输出:lzl

执行结果为“lzl”,分析下上面的代码,f2()执行结果为函数f1的内存地址,即ret=f1;执行ret()等同于执行f1(),执行f1()时与f2()没有任何关系,name=“lzl”与f1()在一个作用域链,函数内部没有变量是会向外找,所以此时变量name值为“lzl”;理解了这个,那么刚才没给出答案的那个终极代码你也知道答案了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#终极版作用域
 
name = "lzl"
 
def f1():
    print(name)
 
def f2():
    name = "eric"
    f1()
 
f2()
 
# 输出:lzl

是的,输出的是“lzl”,记住在函数未执行之前,作用域已经形成了,作用域链也生成了

5、新浪面试题

1
li = [lambda :x for in range(10)]

判断下li的类型?li里面的元素为什么类型?

1
2
3
4
5
print(type(li))
print(type(li[0]))
 
# <class 'list'>
# <class 'function'>

可以看到li为列表类型,list里面的元素为函数,那么打印list里面第一个元素的返回值,此时返回值为多少?

1
2
3
4
5
6
7
8
#lambada 面试题
 
li = [lambda :x for in range(10)]
 
res = li[0]()
print(res)
 
#输出:9

li第一个函数的返回值为9还不是0,记住:函数在没有执行前,内部代码不执行;博客里面的代码可以自己练练,加深下印象

6、补充一个

瞅瞅下面的代码:

1
2
3
4
5
6
7
8
def f1():
    def f2():
        print(name)
    name = 'Jefrey'
    return f2()
f1()
 
# Jefrey

函数内部的变量(name),优先去f2函数内部找,且只能在print(name)之前去定义;如果没有,跳出当前函数一层,去外部找变量定义即f1内部去找,跳出当前f2函数找变量定义时,无论变量定义在函数f2之前还是之后都是可以的;当外部f1有多个定义时,如何执行?

1
2
3
4
5
6
7
8
9
10
def f1():
    name = 'lzl'
    name = 'lianzhilei'
    def f2():
        print(name)
    name = 'Jefrey'
    f2()
f1()
 
# Jefrey

当外部函数里有多个变量定义时,找f2()执行时,执行最近上面的变量的值

最新文章

  1. Nhibernate mapping 文件编写
  2. Uart、SPI和I2C的区别
  3. css实现一个写信的格式
  4. nginx实现ssl反向代理实战
  5. QQ粘性布局
  6. 服务器压力测试 ab
  7. puppet实现主从部署各种软件实战参考模型
  8. PHP实现下载功能之流程分析
  9. SQL Server 2008 R2 主从数据库同步
  10. bzoj1145
  11. Sublime 3 and Python
  12. MediaScanner与音乐信息扫描==
  13. NewsDao
  14. PHP XML 函数
  15. soamanager发布的Webservice服务,调用时出现http500报错
  16. linux 查看ip地址
  17. C++入门程序作业2
  18. svn文件夹解锁批处理
  19. TensorFlow中assign函数
  20. 使用ntlmrelayx在任何地方进行中继凭据

热门文章

  1. maven学习资料
  2. ajax 传递参数中文乱码解决办法
  3. 错误 1 error C4996: &#39;scanf&#39;: This function or variable may be unsafe. Consider using scanf_s instead
  4. JS——覆盖显示,点击显示三层
  5. zookeeper安装与集群搭建
  6. mysql information_schema 数据库简介:
  7. Linux增加用户并赋予权限
  8. redission计数器实现,redisTemplate计数器
  9. node.js安装与入门使用
  10. oracledbconsole db启动问题