python作用域

无函数的作用域

在python中没有块级作用域

什么叫块级作用域呢?先来看个例子:

if 1 == 1:
name= 'alex'
print(name)

运行结果为alex

在javascript、python中运行结果为alex,但是在java和C#中,会抛出异常:没有name的变量

for i in range(10):
name=i
print(name)

结果也是9

为什么会出现这种情况呢,归根结底就是因为块级作用域

在python中,一个tab或者空格缩进,表示一个代码块

  • 在有块级作用域的语言中,比如java/c#,代码中的name只在当前作用域下生效。
  • 在没有块级作用域的语言中,比如python/javascript中,代码中的name变量,不仅在代码块中生效,在代码块外面也一样生效

python中以函数为作用域

再来看一下这个:

def fun():
name ='alex'
fun()
print(name)

在函数的作用域中,变量无法生效的。

总结1

所以我们可以总结一下:python中是以函数作为作用域的,并且python中无块级作用域

python中的作用域链

python中有作用域链,对于变量的查找方式是由内向外查找的,当前作用域中有,使用当前变量设置,如果没有,往上查找,知道找到最后找不到而报错。

看个例子能更为直观些:

name='cc'
def f1():
name='alex'
def f2():
name='bb'
print(name)
f2()
f1()

输出:

bb

按照上面所述,查找name的方式就是从f2函数中查找,如果有就是bb,如果没有,就是f1中的alex,如果还没有就是cc,如果最外面的全局变量中也没有,那么程序必然会报错。

python/javascript中作用域与函数的关系

对于作用域来说,在函数没有执行之前,他的作用域、作用域链均已经确定。

看下例子:

name = 'alex'
def f1(): #作用域1
print(name)
###################
def f2(): #作用域2
name='cc'
f1()
f2()
name = 'alex'
def f1(): #作用域1
print(name)
######################
def f2(): #作用域2
name = 'cc'
return f1
ret = f2()
ret()

上面两个输出均为alex

说下原因吧:我们已经知道了,python中是以函数为作用域的,在作用域1中,作用域会直接用使用全局变量name='alex',但在作用域2中,虽然有一个局部变量name,但在程序最终执行之前,python已经从上到下把作用域和作用域链确定了,就是f1()的执行结果肯定是alex,不受其他因素的影响。

python中的特殊语法

直接上例子吧,据说是一个新浪面试题:

li=[x+100 for x in range(10)]   #在0-9循环,并且每次循环+100
print(li)
lis=[x+100 for x in range(10) if x > 6] #只有x>6时,x+100
print(lis) li1=[lambda: x for x in range(10)] #首先li是一个列表,列表中的元素都是函数
print(li1)
# print(type(li1))
r=li1[0]() #函数加括号执行lambda表达式
print(r) #最后x为9,所以每个元素都是return 9

输出结果:

[100, 101, 102, 103, 104, 105, 106, 107, 108, 109]
[107, 108, 109]
[<function <listcomp>.<lambda> at 0x0000019EC393D598>, <function <listcomp>.<lambda> at 0x0000019EC393D620>, <function <listcomp>.<lambda> at 0x0000019EC393D6A8>, <function <listcomp>.<lambda> at 0x0000019EC393D730>, <function <listcomp>.<lambda> at 0x0000019EC393D7B8>, <function <listcomp>.<lambda> at 0x0000019EC393D840>, <function <listcomp>.<lambda> at 0x0000019EC393D8C8>, <function <listcomp>.<lambda> at 0x0000019EC393D950>, <function <listcomp>.<lambda> at 0x0000019EC393D9D8>, <function <listcomp>.<lambda> at 0x0000019EC393DA60>]
9

Python中:函数在没执行前,内部代码不执行。

所以,我们在看li1=[lambda: x for x in range(10)],这行代码中,lambda:x是一个函数,函数内部x只是一个x变量,不会被赋值,而for x in range(10)的执行结果都是9;所以内部是10个lambda函数,而函数可以认为是lambda : x,但这个x其实已经赋予9的值了,但因为没有执行,暂时是x,加括号后就直接返回9.

其实把他拆开,我们可以这么写一行:

li = []
for i in range(10)
def f1():
return i
li.append(f1)
print(li[1]())

首先for 循环已完成,i已经赋予9,然后f1()执行时,按照作用域链查找,i=9,那么返回就是9了。

那么:

li = []
for i in range(10)
def f1(x=i):
return x
li.append(f1)
print(li[0]())
print(li[1]())
print(li[2]())

输出是

0
1
2

为什么呢,因为x=i是一个表达式,表达式是执行了函数。所以还是要看他的本质,要看函数是否被执行

总结

总结下这篇的重要的三句话吧:

  • python中是以函数作为作用域的,并且python中无块级作用域
  • 对于作用域来说,在函数没有执行之前,他的作用域、作用域链均已经确定。,并且:对于变量的查找方式是由内向外查找的,当前作用域中有,使用当前变量设置,如果没有,往上查找,知道找到最后找不到而报错。
  • 函数在没执行前,内部代码不执行。在碰到lambda时候需要注意!!!

python 3 和2.7 class 类多继承时的区别

在python2.7中,类默认不继承object类,叫经典类;继承object类,叫新式类

在python3中,如果按照2.7中的规则,所有的类都算新式类

多继承并且有共同父类的情况下:

  • 经典类,一条道走到黑,然后再从第二个继承类中找
  • 新式类,查找的最后的终点是共同父类,所以在查找途中如果遇到共同父类,会返回创建对象类下一个父类类中,知道走到最后共同类。

python基础之知识补充-作用域、特殊语法的更多相关文章

  1. 一、python基础相关知识体系

    python基础 a. Python(解释型语言.弱类型语言)和其他语言的区别? 一.编译型语言:一次性,将全部的程序编译成二进制文件,然后在运行.(c,c++ ,go) 运行速度快.开发效率低 二. ...

  2. Python学习---django知识补充之CBV

    Django知识补充之CBV Django: url    -->  def函数      FBV[function based view]  用函数和URL进行匹配 url    --> ...

  3. Python基础灬函数补充(作用域,迭代器,生成器)

    变量作用域 函数里面操作外部变量时,作用域仅限于函数里面. var1 = 123 def func(): var1 = 456 print("函数里:", var1) func() ...

  4. python基础17 ---继承补充知识

    一.继承的顺序 1.在python中的类可以集成多个类,既然是继承多个类就有类的寻找顺序这么一说.其寻找方法就有广度优先和深度优先两种. 2.当类是新式类,多继承的情况下会按照广度优先的顺序查找. 如 ...

  5. 2015/9/19 Python基础(15):变量作用域及生成器

    变量作用域标识符的作用域是定义为其声明的可应用范围,或者即是我们所说的变量可见性.也就是,我们可以在程序的那个部分去访问一个制定的标识符.全局变量与局部变量定义在函数内的变量有局部作用域,在一个模块中 ...

  6. Python基础入门知识

    本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表达式if ...else语 ...

  7. python基础编程: 编码补充、文件操作、集合、函数参数、函数递归、二分查找、匿名函数与高阶函数

    目录: 编码的补充 文件操作 集合 函数的参数 函数的递归 匿名函数与高阶函数 二分查找示例 一.编码的补充: 在python程序中,首行一般为:#-*- coding:utf-8 -*-,就是告诉p ...

  8. Python基础:11变量作用域和闭包

    一:变量作用域 变量可以是局部域或者全局域.定义在函数内的变量有局部作用域,在一个模块中最高级别的变量有全局作用域. 全局变量的一个特征是除非被删除掉,否则它们的存活到脚本运行结束,且对于所有的函数, ...

  9. Python基础、collections补充

    collections collections是Python数据类型的补充,可以实现Counter计数.可命名元组(namedtuple).默认字典.有序字典.双向队列等功能 参考:http://py ...

随机推荐

  1. 第七届蓝桥杯C/C++程序设计本科B组决赛 ——棋子换位(代码补全题)

    棋子换位 有n个棋子A,n个棋子B,在棋盘上排成一行.它们中间隔着一个空位,用“.”表示,比如: AAA.BBB 现在需要所有的A棋子和B棋子交换位置.移动棋子的规则是:1. A棋子只能往右边移动,B ...

  2. 2019-2020-1 20199301《Linux内核原理与分析》第二周作业

    第二周Linux学习笔记 文件打包与解压缩 tar工具打包 tar的解压和压缩都是同一个命令,只需参数不同,使用较方便. 创建一个包时文件名必须紧跟在 -f 之后,解包一个文件(-x参数)到指定路径的 ...

  3. AJAX学习笔记——JSON

    JSON基本概念 1.JSON : JavaScript对象表示法( JavaScript Object Notation ) 2.JSON是存储和交换文本信息的语法,类似XML.它采用键值对的方式来 ...

  4. vue2 自定义键盘事件

  5. 数据库概念 MySQL语法

    数据库概念 将保存的数据部分,存到一个公共的地方,所有的用户涉及到数据相关都必须来这个公共地方查找 MySQL 本质就是一款基于网络通信的应用软件,任何基于网络通信的软件底层都是socket 可以把M ...

  6. 在Vue中加入国际化(i18n)中英文功能

    1.npm安装方法 npm install vue-i18n --save 2.在src资源文件下创建文件夹i18n,i18n下面创建index.js文件,引入VueI18n和导入语言包(按开发需求可 ...

  7. 003_创建simulink文件

    001_创建simulink文件 1. 打开MATLAB,打开simulink 2. 打开空白模块 3. 保存,并打开模块的选择 4. 在模块里面选择后拖出模块后连线 或在搜索名称后拖出来 或在空白的 ...

  8. Neo4j 快速清除数据库数据

    在开发过程中,很多时候需要快(简)速(单)清(粗)除(暴)Neo4j中存在的海量数据节点和关系数据.在这种情况下,delete和detach从性能上都已力不从心.Neo4j官方推荐清库方法,即删除gr ...

  9. Mybatis基础-完整CRUD操作

    步骤一:mybatis基本配置 1)创建Java项目,在lib下导入mybatis所需要的Jar包,包括链接mysql的mysql-connector-java-5.1.7-bin.jar. 2)在s ...

  10. Linux 系统监控shell脚本

    比较粗略的一个脚本:主要监控系统磁盘.CPU.内存.网络流量.tcp连接数等 代码如下: [root@test system_monitor_shell_script]# cat system_mon ...