(一)作用域
想必在上一篇你就已经感受到了好像python中的变量似乎不是随便就能使用的,例如在函数里面可以随意访问到外面的值,而函数外面却不能访问函数里面的值。造成这个的原因就是:作用域不同!
python中程序的变量并不是在那个位置都可以访问的,访问的权限决定于这个变量是在哪里赋值的,变量的作用域分为四种:
- L:local,局部作用域(每一个函数都有一个局部作用域)
- E:enclosing,闭包作用域(所谓闭包就是函数里面定义函数就叫做闭包)包含函数的函数的作用域
- G:glocal:全局作用域,我们平时写代码的地方
- B:build in:内建作用域,系统固定模块里面的变量,如int,str等
关于变量的查找有这样一个规则,L => E => G => B,如果局部作用域里没有改变量,就往闭包里面找,闭包里面也没有,就往全局作用域找,全局作用域也找不到,最后去内建作用域找。最后仍然找不到的话,就会报错。而反过来是不行的。
这就很好的解释了我们开头说的例子。
# 这儿是全局作用域
global_x = 0
# 定义到内建作用域中
build_x = str(global_x)
# print(type(build_x))
# print(build_x+"123")
def outer():
# 这儿是闭包作用域
local_x = 1
print(global_x) # E => G
print(build_x) # E => G => B
# 形成闭包
def inner():
# 这里是局部作用域
inner_x = 2
print(local_x) # L => E
print(global_x) # L => E => G
print(build_x) # L => E => G => B
inner()
outer()
注意:
python中只有模块(module),函数,类(class)会产生新的作用域,而其他的语句都不行,外部都能访问到其变量。
if True:
msg = '123'
sum = 0
print(msg)
for i in range(5):
sum = sum+i
print(sum,i)
那你来试着描述一下,这其中发生了些什么?
sum=0
def add(a,b):
sum = a+b
add(1,2)
print(sum)
这里的这里一共有两个sum,一个局部变量sum,一个是全局变量sum。
那你肯定会问,如果我非要用外面的sum不可呢?
就可以使用global 和 nonlocal关键字。
# global
sum=0
def add(a,b):
global sum # 区别只在这里
sum = a+b
add(1,2)
print(sum)
# nonlocal
def outer():
a=0
def inner():
nonlocal a
a=4
inner()
print(a)
(二)模块
所谓模块,其实就是你将自己编写的代码放到一个文件里面,这个文件就叫做一个模块。
你写的这跟文件里的所有内容都能够引入到其他的代码中所使用。python叶子带了很多的标准库,例如os,http,sys等。都是通过这样的方法引入。引入的关键字为import
.
import 语句的注意事项:
- 需要把import语句放到文件的开始。
- import 后面跟文件名,python会自动根据目录寻找模块。
示例代码:
(1)在当前文件目录下新建两个文件,叫做:a.py、b.py
- a.py
def add(a,b):
return a+b
- b.py
import a
print(a.add(1,2))
还可以使用from…import…
语句,表示从什么模块中,引入某个函数。
例如:
- b.py
from a import add
print(add(2,3))
还可以使用from ...import *
,从某个模块中,引入所有的函数。
例如:
- b.py
from a import *
print(add(3,4))
还还可以使用as取个别名:
from test1 import add as a
print(a(4,5))
注意:python在引入模块的时候,就先会执行一遍引入的模块的内容。
好了引入模块的知识算是学完了,那我们现在知道了,python的模块是一个文件,python的逻辑代码也是一个文件。那只要该文件下建立一个文件,然后输入import *
,直接就把主函数运行了。那岂不是那就出大问题,给人的感觉也是不好的。那么怎么解决这个问题呢?
python给出了解决方案,他给每一个python文件分了状态,如果是当前执行的是这个文件,模块中有一个属性_name_ = _main_
,如果是别人引用,那么这个属性值就会变为_name_ = 文件名
。这样的话,我们就可以通过条件语句给主函数上把锁。
例如:
- c.py
import a
if _name_ ==_main_:
# 在这里执行主函数
print(a.add(1,2))
- d.py
import c
我们执行a.py,就会打印3,但是我们执行d.py就不会有任何输出。
我们可以使用dir()这个函数来输出模块内的所有内容。你也会看到_name_
属性。
print(dir())
(三)包
这就极为简单了,一个包就是一个文件夹,里面存放的是模块。他和文件夹唯一的区别就是里面必须含有一个叫做__init__.py
的文件,是用于对里面的文件新型初始化操作的,尽管这个文件常常是空的。但是这个文件标志着这个文件夹是一个包。
包就是这么简单。完事儿啦。
学到这里,恭喜你,半只脚已经进门了。因为你已经能够读懂大部分的代码了,你所需要的只是不断地练习。但是不得不说,接下来的内容虽然有些难度,如果理解之后,会给你打开一个新天地。接下来的内容是面向对象编程,和类(class)