【python】Ch15_作用域与参数

作用域表示被赋值的参数变量在一个多大的领域里面是有效的,我们就称这个变量参数的作用域是“什么”。一般从小到大的作用域顺序是:本地 -> 函数内 -> 全局 -> 内置。也称作LEGB。


Principle

命名空间是一个 python 用来改变,创建,和查找变量名的地方,作用域的别名,说的是同一件事。从名字到有效空间,都是 python 在赋值的时候背地里一起帮编码人员生成好的东西。变量被赋值的当下位置就是该变量的作用域范围,这也意味着被声明的变量名只能在其所在的空间中被使用,无法跨区域。

变量名的作用域与函数调用完全没有关系,即便两个同样名字的变数要是在不同作用域创建的话,也互不影响运算,例如:

>>> def Func1():
        x = 1
        return x
>>> def Func2():
        x = 10
        return x
>>> for x in range(100):
        print(x)
  • 全局变量 global variable 的有效范围只限定在该一个 .py 文件
  • 内置函数与功能全部都是全局使用的
  • 每次我们利用 def 创建一个函数时,都是定义一个新的本地作用域
  • 赋值的变量名一律都是区域变量名,除非特定宣告成全局的
  • For every variables, they belong to only three types: local, global, and intrinsic effective area.

变量名解析:LEGB

LEGB stands for Local, Enclosing, Blobal, Built-in.
视频链接:https://www.youtube.com/watch?v=QVdf0LgmICw

三个原则:
    1. 本地 -> 函数 -> 全局-> 内置,是查找变量名的顺序
    2. 变量名赋值会创建或改变本地变量

    3. 全局生命改变复制变量名,映射到模块文件内部作用域

本地作用域的变量名可能覆盖全局作用域,内置作用域的变量名也可能被全局作用域的变量名覆盖,导致原本的 function 效果失灵,这点特别需要注意,范例如下:

>>> def hider():
        open = 'spam'
        # ... something here
        open('data.txt')        # this won't work then because the name has been covered
        return open

Because the local variable covered the intrinsic database, the origin is now losing its functionality and therefore hiding the setting somewhere.


最小化全局变量
如果我们希望在一个函数里面宣告一个全局变量,global 这个功能就派上用场了,下面范例:

>>> x = 99
>>> def func1():
        global x
        x = 88
        return x
>>> def func2():
        global x
        x = 77
        return x

本地的 x = 99 会在函数返回的时候消失,反之全局变量将会持续记得他自己被 assign 了什么,python 中使用单线程,还要依靠全局变量因为他们彼此共享内存,互为通信角色。

But, if we are not that familiar with programming, try to avoid the global variables.


最小化文件间的修改
每个模块都是一个属于自己的命名空间,如果需要其他模块的变量,必须使用 import 把该模块引入当下的文件中,一个模块文件的全局变量一旦导入了另一个模块对象后,就会变成了别人的属性:导入这得到被导入的模块文件所有全局变量的访问权。例如:

# in first.py file
>>> x = 99

# in second.py file
>>> import first
>>> first.x = 88
# but when the scale of the program is getting bigger, it would be harder for programmers to find out the actual access in order to change the variables.
# so here is the suggestion: use it less

作用域和嵌套函数
LEGB 原则包含了任意嵌套函数内部的本地作用域,有时这也叫做静态嵌套作用域。听起来有点绕口,下面做一个举例:

>>> def f1():
        x = 99
        def f2():
            print(x)
        f2()
>>> f1()

这个 case 里面,嵌套在 def 里面的 f2 在函数 f1 被调用的时候被运行,f2 在这边只是作为一个临时函数运行在 f1 中。函数能够在整个 def 声明内获取变量名,通过 LEGB 查找法则,自动把 f1 的 x 映射到了 f2 去,不管 f1 有没有被呼叫。


传递函数
参数传递通过的是把对象赋值给本地变量来完成的。不可变参数是通过“值”来传递的,如整数和字符串;而可变对象是通过“指针”来传递的,如列表和字典。下面是一个参数与共享的范例:

>>> def changer(a, b):
        a = 2
        b[0] = 'spam'
>>> x = 1
>>> L = [1, 2]
>>> changer(x, L)
>>> x, L
(1, ['spam', 2])

可能对于编程初学的人来说吃力了点,这边例子功能就是利用 changer 这个 function 把 第二个 argument 里面的第一个元素换成 'spam' 这个东西。于是,在没有直接宣告说 L 改变的情况下,就改变了 L 的内容。如果要避免这种被修改的情况发生,建议使用 tuple 就可以把里面的元素定死在位置上,要是有人要修改,就会报错。

通用 set 函数
如果现在有一个 list 需要挑出两个序列中都出现的元素,set 就是一个可以很好派上用场的工具,可以搜集任意多的数据中出现过的元素总共不重复的有哪些。

>>> L = [1, 1, 1, 2, 3, 3, 3, 4, 5, 6]
>>> T = (2, 2, 2, 3, 3, 4, 4, 5)
>>> set(L)
{1, 2, 3, 4, 5, 6}        # this is not dictionary. this is set class object! mark in mind.
>>> set(T)
{2, 3, 4, 5}        # both tuple and list would be available for set function

下面是使用了可变参数的匹配性是 *args 去收集传入参数,并对任意数目的序列的公共部分筛选的函数编写方法:

>>> def intersect(*args):
        res = []
        for x in args[0]:              # scan first sequence
            for other in args[1:]:     # for all other args
                if x not in other:
                    break
                else:
                    res.append(x)
        return res
>>> def union(*args):
        res = []
        for seq in args:               # for all args
            for x in seq:              # for all nodes
                if not x in res:
                    res.append(x)
        return res

里面用上了上一届介绍的技巧,请自行查看:https://blog.csdn.net/qq_37165755/article/details/79907580

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值