Python函数高级(命名空间、作用域、装饰器)

目录
  • 一、名称空间和作用域
    • 1、命名空间(Namespace)
      • 1、一般有三种命名空间:
      • 2、命名空间查找顺序:
      • 3、命名空间的生命周期:
    • 2、作用域:
    • 3、全局变量和局部变量
    • 4、函数对象+作用域应用
    • 5、global关键字修改全局作用域中的变量
    • 6、nonlocal关键字修改嵌套作用域中的变量。
  • 二、闭包函数
    • 应用领域:
  • 三、函数装饰器
  • 四、无参装饰器
    • 1、被装饰函数有返回值:
    • 2、被装饰函数需要传参:
    • 3、装饰器模板
    • 4、装饰器语法糖:
  • 五、带参数的装饰器
    • 3、有参三层装饰器:
  • 六、类装饰器
  • 七、装饰器顺序
  • 八、装饰器使用场景
    • 授权(Authorization)
    • 日志(Logging)

一、名称空间和作用域

1、命名空间(Namespace)

命名空间是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。

命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。

1、一般有三种命名空间:

  • 内置名称空间(built-in names):存放内置的名字,如len/eval/enumerate/bytes/max/min/sorted/map/filter....
  • 全局名称空间(global names):模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
  • 局部名称空间(local names):函数内部的名字都是局部名称空间,不同函数内部的名字互不干涉。

2、命名空间查找顺序:

如果找不到变量 runoob,它将放弃查找并引发一个 NameError 异常:

NameError: name 'runoob' is not defined。
  • 查找顺序:假设我们要使用变量 runoob,则 Python 的查找顺序为:局部的命名空间去 -> 全局命名空间 -> 内置命名空间
  • 执行顺序:先内置(Python解释器启动的时候才会生成)-> 全局(文件执行的时候才会生成)-> 局部(函数调用的时候才会生成)

3、命名空间的生命周期:

命名空间的生命周期取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束。

因此,我们无法从外部命名空间访问内部命名空间的对象。

如下图所示,相同的对象名称可以存在于多个命名空间中。

2、作用域:

作用域就是一个 Python 程序可以直接访问命名空间的正文区域。

全局名称空间和局部名称空间中可能会存在名字相同的变量,但是这两个变量互不影响。

Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。

Python的作用域一共有4种,分别是:

  • L(Local):最内层,包含局部变量,比如一个函数/方法内部。
  • E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
  • G(Global):当前脚本的最外层,比如当前模块的全局变量。
  • B(Built-in): 包含了内建的变量/关键字等。,最后被搜索

对于变量作用域,变量的访问以: L –> E –> G –>B 的 规则查找。

在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。

举例:

x = 1

def func():
    print(x)  #10

x = 10
func()

内置作用域是通过一个名为 builtin 的标准模块来实现的,但是这个变量名自身并没有放入内置作用域内,所以必须导入这个文件才能够使用它。

在Python3.0中,可以使用以下的代码来查看到底预定义了哪些变量:

import builtins
print(dir(builtins))

Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,

如下代码:实例中 msg 变量定义在 if 语句块中,但外部还是可以访问的。如果将 msg 定义在函数中,则它就是局部变量,外部不能访问。

if True:
    msg = 'I am from Runoob'
print(msg)
# 'I am from Runoob'

3、全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。

# 作用域注意点
x = 1

def f1():  # 定义阶段x=1
    print(x)  #1

def f2():
    x = 2  #此x为f2函数的局部变量,f1无法直接访问
    f1()

f2()

4、函数对象+作用域应用

def f1():
    def inner():
        print('from inner')
    return inner

f = f1()  # from inner   。把局部定义的函数inner()放在全局之中

def bar():
    f()

bar()

5、global关键字修改全局作用域中的变量

函数内可以访问全局变量,但不能直接更新(修改)其值,可以加上 global 引用以更新变量值 :

x = 1

def f1():
    x = 2

    def f2():
        global x  # 修改全局
        x = 3

    f2()

f1()
print(x)  # 3

6、nonlocal关键字修改嵌套作用域中的变量。

如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了

x = 1

def f1():
    x = 2

    def f2():
        nonlocal x
        x = 3

    f2()
    print(x)  # 3

f1()

二、闭包函数

闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用)。

闭包指的是:函数内部函数对外部作用域而非全局作用域的引用。

def outter(x):
    x = 1

    def inner():
        print(x)

    return inner #返回的是函数名(函数对象)

f = outter(2)

f()  # 1
f()  # 1
f()  # 1
# 查看闭包的元素
print(f.__closure__[0].cell_contents)  # 1

闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域。

应用领域:

延迟计算(原来我们是传参,现在我们是包起来)、爬虫领域。

import requests

def outter(url):
    def get():
        response = requests.get(url)
        print(f"done: {url}")

    return get

baidu = outter('https://www.baidu.com')
python = outter('https://www.python.org')

baidu()
baidu()

python()
python()

三、函数装饰器

装饰器指的是为被装饰器对象添加额外功能。因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能。装饰器的实现必须遵循两大原则:

  • 不修改被装饰对象的源代码
  • 不修改被装饰对象的调用方式

装饰器其实就是在遵循以上两个原则的前提下为被装饰对象添加新功能。

不改变函数体代码,并且不改变函数调用方式,它本质就是一个闭包函数。

def f1(x):
    def f2():
        print(x)  # 10
    return f2

f2 = f1()
f2()  # f2()

在不改变当前函数的情况下, 给其增加新的功能:

def log(pr):  # 将被装饰函数传入
    def wrapper():
        print("**********")
        return pr()  # 执行被装饰的函数

    return wrapper  # 将装饰完之后的函数返回(返回的是函数名)

@log
def pr():
    print("我是小小洋")

pr()

# **********
# 我是小小洋

回调函数和返回函数的实例就是装饰器。

四、无参装饰器

举例:

import time

def index():
    print('welcome to index')
    time.sleep(1)

def time_count(func):
    # func = 最原始的index
    def wrapper():
        start = time.time()
        func()
        end = time.time()
        print(f"{func} time is {start - end}")  #  time is -1.0038220882415771

    return wrapper

index = time_count(index)  # index为被装饰函数index的内存地址,即index = wrapper
index()  # wrapper()

1、被装饰函数有返回值:

如果原始的被装饰函数index()有返回值的时候,wrapper()函数的返回值应该和index()的返回值相同,也就是说,我们需要同步原始的index()和wrapper()方法的返回值。

import time

def index():
    print('welcome to index')
    time.sleep(1)
    return 123

def time_count(func):
    # func = 最原始的index
    def wrapper():
        start = time.time()
        res1 = func()
        end = time.time()
        print(f"{func} time is {start - end}")  #  time is -1.0050289630889893
        return res1

    return wrapper

index = time_count(index)
res = index()
print(f"res: {res}")  #
res: 123

2、被装饰函数需要传参:

如果原始的被装饰函数index()方法需要传参,那么我们之前的装饰器是无法实现该功能的,由于有wrapper()=index(),所以给wrapper()方法传参即可。

import time

def index():
    print('welcome to index')
    time.sleep(1)
    return 123

def home(name):
    print(f"welcome {name} to home page")
    time.sleep(1)
    return name

def time_count(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print(f"{func} time is {start-end}") #  time is -1.0039079189300537
        return res

    return wrapper

home = time_count(home)

res = home('egon')
print(f"res: {res}") #res: egon

3、装饰器模板

def deco(func):
    def wrapper(*args,**kwargs):
        res = func(*args,**kwargs)
        return res
    return wrapper

4、装饰器语法糖:

在被装饰函数正上方,并且是单独一行写上@装饰器名

import time

def time_count(func): #装饰器
    # func = 最原始的index
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print(f"{func} time is {start-end}") # time is -1.0005171298980713
        return res

    return wrapper

@time_count  # home = time_count(home)
def home(name):
    print(f"welcome {name} to home page") #welcome egon to home page
    time.sleep(1)
    return name

res = home('egon')
print(f"res: {res}") #res: egon

五、带参数的装饰器

注意无参装饰器只套两层。

import time

current_user = {'username': None}

def login(func):
    # func = 最原始的index
    def wrapper(*args, **kwargs):
        if current_user['username']:
            res1 = func(*args, **kwargs)
            return res1

        user = input('username: ').strip()
        pwd = input('password: ').strip()

        if user == 'nick' and pwd == '123':
            print('login successful')
            current_user['username'] = user
            res1 = func(*args, **kwargs)
            return res1
        else:
            print('user or password error')

    return wrapper

@login
def index():
    print('welcome to index')
    time.sleep(1)

res = index()

#username: nick
#password: 123
#login successful
#welcome to index

我们首先看看三层闭包怎么运用。

def f1(y):
    def f2():
        x = 1

        def f3():
            print(f"x: {x}")  # x: 1
            print(f"y: {y}")  # x: 1

        return f3
    return f2

f2 = f1(2)
f3 = f2()
f3()

3、有参三层装饰器:

在函数中嵌入装饰器

import time

current_user = {'username': None}

def auth(engine='file'):
    def login(func):
        def wrapper(*args, **kwargs):
            if current_user['username']:
                res = func(*args, **kwargs)
                return res

            user = input('username: ').strip()
            pwd = input('password: ').strip()

            if engine == 'file':
                print('base of file')
                if user == 'nick' and pwd == '123':
                    print('login successful')
                    current_user['username'] = user
                    res = func(*args, **kwargs)
                    return res
                else:
                    print('user or password error')
            elif engine == 'mysql':
                print('base of mysql, please base of file')
        return wrapper
    return login

@auth(engine='file')
def index():
    print('welcome to index')
    time.sleep(1)

res = index()

username: nick 
password: 123 
base of file 
login successful 
welcome to index

六、类装饰器

没错,装饰器不仅可以是函数,还可以是类,相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器主要依靠类的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。

class Foo(object):
    def __init__(self, func):
        self._func = func

    def __call__(self):
        print ('class decorator runing')
        self._func()
        print ('class decorator ending')

@Foo
def bar():
    print ('bar')

bar()

functools.wraps

使用装饰器极大地复用了代码,但是他有一个缺点就是原函数的元信息不见了,比如函数的docstring、__name__、参数列表,先看例子:

# 装饰器
def logged(func):
    def with_logging(*args, **kwargs):
        print func.__name__      # 输出 'with_logging'
        print func.__doc__       # 输出 None
        return func(*args, **kwargs)
    return with_logging

# 函数
@logged
def f(x):
   """does some math"""
   return x + x * x

logged(f)

不难发现,函数 f 被with_logging取代了,当然它的docstring,__name__就是变成了with_logging函数的信息了。好在我们有functools.wraps,wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器里面的 func 函数中,这使得装饰器里面的 func 函数也有和原函数 foo 一样的元信息了。

from functools import wraps

def logged(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
        print func.__name__      # 输出 'f'
        print func.__doc__       # 输出 'does some math'
        return func(*args, **kwargs)
    return with_logging

@logged
def f(x):
   """does some math"""
   return x + x * x

七、装饰器顺序

一个函数还可以同时定义多个装饰器,比如:

@a
@b
@c
def f ():
    pass

它的执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器,它等效于

f = a(b(c(f)))

八、装饰器使用场景

现在我们来看一下装饰器在哪些地方特别耀眼,以及使用它可以让一些事情管理起来变得更简单。

授权(Authorization)

装饰器能有助于检查某个人是否被授权去使用一个web应用的端点(endpoint)。它们被大量使用于Flask和Django web框架中。这里是一个例子来使用基于装饰器的授权:

from functools import wraps

def requires_auth(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if not auth or not check_auth(auth.username, auth.password):
            authenticate()
        return f(*args, **kwargs)
    return decorated

日志(Logging)

日志是装饰器运用的另一个亮点。这是个例子:

from functools import wraps

def logit(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
        print(func.__name__ + " was called")
        return func(*args, **kwargs)
    return with_logging

@logit
def addition_func(x):
   """Do some math."""
   return x + x

result = addition_func(4)
# Output: addition_func was called

到此这篇关于Python函数高级用法的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Python名称空间与作用域

    目录 一 名称空间 1.1 内建名称空间 1.2 全局名称空间 1.3 局部名称空间 二 作用域 2.1 全局作用域与局部作用域 2.2 作用域与名字查找的优先级 一 名称空间 名称空间即存放名字与对象映射/绑定关系的地方.对于x=3,Python会申请内存空间存放对象3,然后将名字x与3的绑定关系存放于名称空间中,del x表示清除该绑定关系. ​ 在程序执行期间最多会存在三种名称空间 1.1 内建名称空间 伴随python解释器的启动/关闭而产生/回收,因而是第一个被加载的名称空间,用来存放

  • Python利用命名空间解析XML文档

    问题 你想解析某个XML文档,文档中使用了XML命名空间. 解决方案 考虑下面这个使用了命名空间的文档: <?xml version="1.0" encoding="utf-8"?> <top> <author>David Beazley</author> <content> <html xmlns="http://www.w3.org/1999/xhtml"> <he

  • Python命名空间及作用域原理实例解析

    Python命名空间和作用域 总结 emmm,这一块讲了2个内容,一个是命名空间,一个是作用域.一个一个说吧 命名空间 A namespace is a mapping from names to objects.Most namespaces are currently implemented as Python dictionaries 上边这段是官方文档定义的,简单来说就是名字到对象的映射,我们知道,python的一切都是对象,你所定义的变量名其实只是个引用.这样就好理解了.python的

  • Python中变量的作用域详解

    目录 1.作用于的概念 2.局部变量 3.全局变量 4.变量的查找 5.作用域中可变数据类型变量 6.多函数程序执行流程 总结 1.作用于的概念 变量作用域指的是变量生效的范围,在Python中一共有两种作用域. 全局作用域 全局作用域在程序执行时创建,在程序执行结束时销毁.所有函数以外的区域都是全局作用域.在全局作用域中定义的变量,都属于全局变量,全局变量可以在程序的任意位置被访问. 函数作用域 函数作用域在函数调用时创建,在调用结束时销毁.函数每调用一次就会产生一个新的函数作用域(不调用不产

  • Python的装饰器详情介绍

    目录 1.定义及使用 2.@classmethod 1.定义及使用 例1:装饰器定义: def 装饰器函数(外部函数):            def 内联函数(*args,**kwargs):                ...前置装饰...                外部函数(*args,**kwargs)                ...后置装饰...            return 内联函数  例2:装饰器两种调用方式 第一种:装饰器函数(外部函数)(参数1,参数2....

  • 深入了解python装饰器

    目录 一.装饰器 1.相关知识点 2.语法糖 3.装饰器模板 4.有参装饰器 一.装饰器 1.相关知识点 *args:负责将多余的位置实参汇总,赋值给args **kwargs:负责将多余的关键字实参汇总,赋值给kwargs 命名空间与作用域 函数对象: 可以把函数当成参数传入 可以把函数当做返回值返回 函数的嵌套定义:在函数内定义函数 闭包函数:父函数的返回值为一个函数,被返回的函数调用了父函数的局部变量,且该函数可以在父函数外部执行 装饰器: 装饰器:定义一个为其他函数添加功能的函数 为什么

  • 浅析Python的命名空间与作用域

    名称空间 名称空间(namespaces):用于存放名字与内存地址绑定关系的地方,是对栈区的划分 作用:名称空间可以使栈区中存放相同的名字,从而解决命名冲突 名称空间分为三种: 内置名称空间 全局名称空间 局部名称空间 内置名称空间 内置名称空间:用于存放Python解释器中内置的名字 生命周期:Python解释器启动则产生,Python解释器关闭则销毁 例如:print.input.int ... 全局名称空间 全局名称空间:运行顶级代码所产生的名字,或者说除函数内定义以及内置的外,剩下的都是

  • python命名空间(namespace)简单介绍

    命名空间: 每一个作用域变量存储的位置,或者解释为 存储作用域中变量的字典. 作用: 获取想查看某个作用域中的变量名.变量值. 使用方法: locals() #当前命名空间 1. 效果图: 2. 代码 a=10 b=20 # 定义一个变量接收全局命名空间里的变量名.变量值 global_namespace=locals() print(global_namespace) print('\n\n\n') def one(): c=30 d=40 # 定义一个变量接收局部命名空间里的变量名.变量值

  • python 中的命名空间,你真的了解吗?

    写在之前 命名空间,又名 namesapce,是在很多的编程语言中都会出现的术语,估计很多人都知道这个词,但是让你真的来说这是个什么,估计就歇菜了,所以我觉得 "命名空间" 有必要了解一下. 全局变量 & 局部变量 全局变量和局部变量是我们理解命名空间的开始,我们先来看一段代码: x = 2 def func(): x = 3 print('func x ---> ',x) func() print('out of func x ---> ',x) 这段代码输出的结

  • Python函数高级(命名空间、作用域、装饰器)

    目录 一.名称空间和作用域 1.命名空间(Namespace) 1.一般有三种命名空间: 2.命名空间查找顺序: 3.命名空间的生命周期: 2.作用域: 3.全局变量和局部变量 4.函数对象+作用域应用 5.global关键字修改全局作用域中的变量 6.nonlocal关键字修改嵌套作用域中的变量. 二.闭包函数 应用领域: 三.函数装饰器 四.无参装饰器 1.被装饰函数有返回值: 2.被装饰函数需要传参: 3.装饰器模板 4.装饰器语法糖: 五.带参数的装饰器 3.有参三层装饰器: 六.类装饰

  • Python实现对一个函数应用多个装饰器的方法示例

    本文实例讲述了Python实现对一个函数应用多个装饰器的方法.分享给大家供大家参考,具体如下: 下面的例子展示了对一个函数应用多个装饰器,可以加多个断点,在debug模式下,查看程序的运行轨迹... #!/usr/bin/env python #coding:utf-8 def decorator1(func): def wrapper(): print 'hello python 之前' func() return wrapper def decorator2(func): def wrapp

  • python GUI库图形界面开发之PyQt5信号与槽的高级使用技巧装饰器信号与槽详细使用方法与实例

    装饰器信号与槽 所谓装饰器信号与槽,就是通过装饰器的方法来定义信号与槽函数,具体的使用方法如下 @PyQt5.QtCore.pyqtSlot(参数) def on_发送者对象名称_发射信号名称(self,参数): pass 这种方法有效的前提是下面的函数已经执行: QMetaObject.connectSlotsByName(QObject) 在上面的代码中,'发送者对象名称'就是使用setObjectName函数设置的名称,因此自定义槽函数的命名规则也可以看做:on+使用setObjectNa

  • 深入理解python中的闭包和装饰器

    python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure). 以下说明主要针对 python2.7,其他版本可能存在差异. 也许直接看定义并不太能明白,下面我们先来看一下什么叫做内部函数: def wai_hanshu(canshu_1): def nei_hanshu(canshu_2): # 我在函数内部有定义了一个函数 return canshu_1*canshu_2 return

  • python总结之闭包和装饰器

    目录 一.装饰器 1. 装饰器的简单介绍 2. 装饰器的解析过程 二.闭包 三.闭包中nonlocal语句的使用 1. 外部变量的引用和改写 2. nolocal的使用及特点 四.闭包与装饰器 五.闭包的作用 六.几个小栗子 栗子1: 栗子2: 栗子3 七.特殊的装饰器 property 装饰器 1. 我们为什么需要用到property 2. 使用Getters和Setters 3. property的作用 4. 小栗子 staticmethod装饰器和classmethod装饰器 step1:

  • 分析Python中设计模式之Decorator装饰器模式的要点

    先给出一个四人团对Decorator mode的定义:动态地给一个对象添加一些额外的职责. 再来说说这个模式的好处:认证,权限检查,记日志,检查参数,加锁,等等等等,这些功能和系统业务无关,但又是系统所必须的,说的更明白一点,就是面向方面的编程(AOP). 在Python中Decorator mode可以按照像其它编程语言如C++, Java等的样子来实现,但是Python在应用装饰概念方面的能力上远不止于此,Python提供了一个语法和一个编程特性来加强这方面的功能.Python提供的语法就是

  • python 一篇文章搞懂装饰器所有用法(建议收藏)

    01. 装饰器语法糖 如果你接触 Python 有一段时间了的话,想必你对 @ 符号一定不陌生了,没错 @ 符号就是装饰器的语法糖. 它放在一个函数开始定义的地方,它就像一顶帽子一样戴在这个函数的头上.和这个函数绑定在一起.在我们调用这个函数的时候,第一件事并不是执行这个函数,而是将这个函数做为参数传入它头顶上这顶帽子,这顶帽子我们称之为装饰函数 或 装饰器. 你要问我装饰器可以实现什么功能?我只能说你的脑洞有多大,装饰器就有多强大. 装饰器的使用方法很固定: 先定义一个装饰函数(帽子)(也可以

  • python的迭代器,生成器和装饰器你了解吗

    python 迭代器与生成器,装饰器 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束. 迭代器有两个基本的方法:iter() 和 next(). 字符串,列表或元组对象都可用于创建迭代器: list1=[1,2,3] s=iter(list1) # 创建迭代器对象 print(next(s)) # 输出迭代器的下一个元素 print(next(s)) print(next(s)) 直到计算出最后一个元素,没有更多的元素时,抛出StopIteration的错误 迭代器对象可以使用

  • python中property和setter装饰器用法

    作用:调用方法改为调用对象, 比如 : p.set_name() 改为 p.set_name 区别:前者改变get方法,后者改变set方法 效果图: 代码: class Person: def __init__(self,name): self._name = name def get_name(self): return self._name def set_name(self,name): self._name = name p = Person('小黑') print(p.get_name

  • Python函数中的作用域规则详解

    目录 1.简单介绍一下闭包 2.在Python中,并不是任何代码块都能引入新的作用域 3.在Python中,名字绑定在所属作用域中引入新的变量,同时绑定到一个对象. 总结 Python是静态作用域语言,但是它自身是一个动态语言.在Python中变量的作用域是由变量在代码中的位置决定的,与C语言有些相似,但不是完全一样. 在Python 2.0及之前的版本中,Python只支持3种作用域,即局部作用域,全局作用域,内置作用域:在Python2.2中,Python正式引入了一种新的作用域 — 嵌套作

随机推荐