zoukankan      html  css  js  c++  java
  • 大爽Python入门教程 62 变量进阶 局部变量`local`与全局变量`global`

    大爽Python入门公开课教案 点击查看教程总目录

    1 定义

    这里来看一个例子。
    不妨猜一下这个输出是多少。

    def change_local(x):
        x += 1
    
    x = 5
    change_local(x)
    print(x)
    

    答案是

    5
    

    这个例子中,函数内部的改动,没有对函数外部生效。
    这是因为函数内部的x和函数外面的x其实是两个。

    函数外面定义的,是全局(global)变量。
    函数里面定义的,是局部(local)变量。
    在python中,局部变量和全局变量的定义差不多就是这样。

    把上面的代码这么来写,应该就很容易看懂了

    def change_local(local_x):
        local_x += 1
    
    gloabl_x = 5
    change_local(gloabl_x)
    print(gloabl_x)
    

    2 作用域

    什么是作用域?
    可以简单理解为,能生效的范围,
    或者说能使用能调用的范围。

    之前讲过,变量要先声明后调用,
    在声明之前调用,会报错
    NameError: name 'var' is not defined 其中var是调用的变量名

    局部变量

    局部变量的作用域是在函数内,
    即在函数内能调用(先声明后调用),
    函数外调用会报错NameError

    示例如下

    def create_local():
        x = 1
    
    create_local()
    print(x)
    

    报错如下

    NameError: name 'x' is not defined
    

    全局变量

    全局变量的作用域是整个程序(目前可以简单理解为整个代码文件),
    即在所有位置都能调用(先声明后调用),
    也包括函数里面

    x = 10
    
    def use_global():
        print(x)
    
    use_global()
    

    输出为

    10
    

    x的声明放在函数声明之后都是可以的,只要保证在调用之前就先行。

    def use_global():
        print(x)
    
    x = 10
    use_global()
    

    此时输出也是10

    x的声明放在函数调用之后则不行,会报错,如下

    def use_global():
        print(x)
    
    use_global()
    x = 10
    

    会报错

    NameError: name 'x' is not defined
    

    优先级

    函数中,有同名的全局变量和局部变量时,
    优先使用局部变量。
    示例如下

    def use_who():
        x = 5
        print(x)
    
    x = 10
    use_who()
    

    输出如下

    5
    

    3 修改全局变量

    在函数外,修改全局变量很简单,
    即正常的修改或赋值。

    函数内如何修改全局变量呢,
    或者说让函数内的修改在函数外生效。

    函数内可以调用全局变量,但是不能直接修改,
    直接修改要么不会生效,要么会报错。

    不生效

    x = 20
    
    def invalid_change():
        x = 10
    
    invalid_change()
    print(x)
    
    x = 20
    
    def invalid_change(x):
        x = 10
    
    invalid_change(x)
    print(x)
    

    两段代码输出都是20
    这个现在大家应该能理解。

    简单来讲,就是在函数内部使用的x,
    其声明是在函数内部的,是局部变量,

    正确方法

    def change():
        global x
        x = 20
    
    x = 10
    change()
    print(x)
    

    输出如下

    20
    

    即在本来使用局部变量的函数区域内,
    使用global进行全局变量声明,则此时的调用和修改是在全局上生效的。

    注意: 可以认为只有这个写法。
    此时不能通过函数传参x了,此时会报错SyntaxError
    示例如下

    def change(x):
        global x
        x = 20
    
    x = 10
    
    change(x)
    print(x)
    

    报错

    SyntaxError: name 'x' is parameter and global
    

    参数会和全局变量声明冲突

    4 直接修改报错探究

    偏难,属于探究内容

    直接修改报错

    那么如果不声明,直接在函数内部先调用全局变量并修改呢。

    x = 20
    
    def wrong_change():
        x += 1
    
    wrong_change()
    print(x)
    

    其报错如下

    UnboundLocalError: local variable 'x' referenced before assignment
    

    这个错误现在看英文,比较难理解。

    换个写法还报错

    我们换个写法,并逐步分析。
    x += 1 可以换成 x = x + 1

    x = 20
    
    def wrong_change():
        x = x + 1
    
    wrong_change()
    print(x)
    

    此时仍然报错UnboundLocalError,和上面一样。

    拆开执行不报错

    那么把赋值符号两边的拆开执行看看。

    x = 20
    
    def wrong_change():
        print(x+1)
    
    wrong_change()
    

    这个能执行,输出为21

    x = 20
    
    def wrong_change():
        x = 20 + 1
    
    wrong_change()
    

    这个也可以执行,无输出(未print)

    合到一起再报错

    但是将这两个合到一起,就无法执行了。
    即如下

    x = 20
    
    def wrong_change():
        print(x+1)
        x = 20 + 1
    
    wrong_change()
    

    会报错

    UnboundLocalError: local variable 'x' referenced before assignment
    

    这是为什么呢?

    原因

    因为函数里面这个x只能有一个意义,或者说一个身份。
    它可以是全局变量(此时不是局部),也可以是局部变量(此时不是全局)。

    但它不能同时都是,不能一个函数里面,
    第一行的x是全局变量,第二行的x是局部变量。

    再回来看报错,这种冲突情况下,
    会认为x是局部变量,所以错误在于赋值之前进行调用。

  • 相关阅读:
    PAT (BL) 1001
    mysql启动报错:/usr/bin/mysqld_safe: line 183: 17006 Killed nohup /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin......
    动态规划:某个单词增加,删除,替换字母而成为另一个单词的最小变更次数?
    ng-class最好用的一种方法
    java数据结构基本框架
    后台运行tomcat和mysql的方法
    mysql无法开启,报错:MySQL Daemon failed to start.
    linux CentOS6.5 yum安装mysql 5.6
    idea mybatis报错:<statement> or DELIMITER expected, got 'id'
    angularjs $http与springmvc @RequestBody
  • 原文地址:https://www.cnblogs.com/BigShuang/p/15621667.html
Copyright © 2011-2022 走看看