zoukankan      html  css  js  c++  java
  • 变量作用域

    Date: 2019-05-27

    Author: Sun

    变量由作用范围来限制,按照作用域分类可分为:

    • 全局(global): 在函数外部定义
    • 局部(local):在函数内部定义

    1. 命名空间

    ​ 比如有一个学校,有5个班级,在2班和4班中都有一个叫“小明”的同学,如果在学校的广播中呼叫“小明”时,2班和4班中的这2个人就纳闷了,你是喊谁呢!!!如果是“2班的小王”的话,那么就很明确了,那么此时的2班就是小王所在的范围,即命名空间

    Python中有三种命名空间

    a) 局部,函数内的命名空间就是局部的;

    b) 全局,模块内的命名空间就是全局的;

    c) 内置,包括异常类型、内建函数和特殊方法,可以代码中任意地方调用;

    命名空间特点

    ​ Python会把命名后的变量和函数分配到不同的命名空间,并通过名称来识别它们。

    ​ Python命名空间是名称到对象的映射,这就像是字典,键名是变量名,值是变量的值。

    在Python程序执行过程中,会有局部命名空间、全局命名空间和内建命名空间同时存在。

    ​ 局部命名空间记录函数内部的变量、传入函数的参数、嵌套函数等被命名的对象;

    ​ 全局命名空间记录模块的变量、函数、类及其它导入的模块等被命名的对象;

    locals() 和globals()

    在python中,变量是以字典形式存储的存储的

    globals()是全局变量; locals()则是局部变量

    # -*- coding: utf-8 -*-
    __author__ = 'sun'
    __date__ = '2019/5/27 18:35'
    
    k = 100
    
    def print_1():
        i = 1
        j = 2
        print('locals():', locals())
        print('globals():', globals())
    
    print_1()
    

    输出:

    locals(): {'j': 2, 'i': 1}
    globals(): {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000028171B0EFD0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/Tx_Project/basic_project/day02/demo/test3.py', '__cached__': None, '__author__': 'sunnychou', '__date__': '2019/5/18 18:35', 'k': 100, 'print_1': <function print_1 at 0x0000028171A12EA0>}
    

    案例

    ​ 内建命名空间记录Python自身提供的函数、模块等被命名的对象。

    >>> x = 3
    >>> globals()
    {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'x': 3, '__package__': None}
    

    ​ 可以看到变量x,3以字典的形式存放在globals空间内。以之对应的名字空间还有:locals()。

    >>> locals()
    {'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, 'x': 3, '__package__': None}
    

    实际上,你可以通过向名字添加键名和值:

    >>> globals()['y'] = 5
    >>> y
    5
    

    全局变量与局部变量

    全局变量是在整个py文件中声明,全局范围内都可以访问

    局部变量是在某个函数中声明的,只能在该函数中调用它,如果试图在超出范围的地方调用, 就会出问题

    全局变量与局部变量两者的本质区别就是在于作用域

    2.变量作用域

    作用域是针对变量而言,指申明的变量在程序里的可应用范围。或者称为变量的可见性。

    按照作用域划分,可以分为:

    • L:Local,局部作用域

    • E:Enclosing,闭包作用域【闭包外的函数中定义的变量】

    • G:Global,全局作用域 在所有函数外定义的变量

    • B:Built-in,內建作用域【内置作用域】

    说明

    ​ 一般在函数体外定义的变量成为全局变量,在函数内部定义的变量称为局部变量

    ​ 全局变量所有作用域都可读,局部变量只能在本函数可读

    ​ 函数在读取变量时,优先读取函数本身自有的局部变量,再去读全局变量

    ​ 全局变量在局部可以使用(即函数内部可以方位函数外部定义的变量)

    案例分析

    #1 局部作用域  
    #局部变量只能在函数内部使用,外部无法引用
    #局部变量的作用域从定义开始到函数体结束
    def demo():
        num = 20  #局部变量  
        print(num)
    demo()
    #print(num) 错误
    
    #函数作用域
    def outter():
       x = 10   #函数作用域,从定义开始到本函数结束
       def inner():
          y = x  #在闭包中可以引用
          print(y)
       return inner
    pf = outter()
    pf()  #执行闭包
    print(pf.__closure__)
    
    #全局作用域
    x = 100    #全局作用域  从定义开始到本文件结束
    def demo():
       print(x)
    print(x)
    
    #内建作用域,是指系统内建的函数或常量,在系统载入时加载,在所有模块中都可以直接引用
    #比如说系统函数
    print(max(1,2,3))  #max函数就是内建作用域  哪里都可以引用
    def  demo():
        x = 30
        y = 50
        print(max(x, y))
    

    变量作用域查找规则

    以 L --> E --> G -->B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,最后到内建作用域中找。

    python作用域种类

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

    # -*- coding: utf-8 -*-
    __author__ = 'sun'
    __date__ = '2019/5/27 13:52'
    
    for i in range(5):
        name = "andy"
    
    print(name)
    for i in range(10):
        age = i
    
    print(age)
    

    输出:

    andy
    9
    

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

    (2)局部作用域

    ​ Python中没有块级作用域,但是有局部作用域

    # -*- coding: utf-8 -*-
    __author__ = 'sun'
    __date__ = '2019/5/27 13:52'
    
    # 局部作用域
    def func():
        name = "sunny"
    
    print(name)
    
    

    ​ name变量只在func()函数内部中生效,所以在全局中是没法调用的

    问题:

    ​ 如果在print(name)前调用func()函数呢?对结果是否有影响?

    (3)闭包作用域

    ​ 闭包的作用域,是一个或多个命名空间按照一定规则叠加影响代码区域;运行时动态的作用域,是按照特定层次组合起来的命名空间。

    # -*- coding: utf-8 -*-
    __author__ = 'sun'
    __date__ = '2019/5/27 13:52'
    i = 100
    
    def g():
        print(i)
    
    def f():
        i = 200
        g()
    
    f()
    
    

    上述运行结果是100

    (4)全局作用域

    先执行如下程序,观察结果

    # -*- coding: utf-8 -*-
    __author__ = 'sun'
    __date__ = '2019/5/27 13:52'
    
    number = 100
    
    def process():
        i = 5                 #局部变量,局部作用域
        number += 1
        print(f"i is {i}, number is {number}")
    
    process()
    
    

    此时会出现UnboundLocalError: local variable 'number' referenced before assignment错误。

    问题:如何让一个函数内能访问一个全局变量呢?

    # -*- coding: utf-8 -*-
    __author__ = 'sun'
    __date__ = '2019/5/27 13:52'
    
    number = 100
    
    def process():
        i = 5                 #局部变量,局部作用域
        global number
        number += 1
        print(f"i is {i}, number is {number}")
    
    
    process()
    
    

    通过以上例子,可以知道,通过global关键字。

  • 相关阅读:
    centos下修改ip
    在sql2008的实例 中 编写存储过程 读取 版本为sql2005 的实例 中的某个数据库里的数据
    解决javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure报错
    Micronaut事务管理
    [make] 第二章 makefile 总述
    [make] 第一章 make 介绍
    [other] AutoHotKey.ahk
    2021年11月国产数据库大事记墨天轮
    风云再起之国产数据库风云榜2021年12月
    2021年12月墨天轮国产数据库排行榜: openGauss节节攀升拿下榜眼,GaussDB与TDSQL你争我夺各进一位
  • 原文地址:https://www.cnblogs.com/sunBinary/p/10934238.html
Copyright © 2011-2022 走看看