zoukankan      html  css  js  c++  java
  • 参数的作用域

    1、作用域 :函数外的变量的作用域为全局作用域(命名空间对应全局命名空间),函数体内的变量(未用global声明)的作用域为内部作用域(对应局部命名空间);函数体内的变量称为局部变量

    >>> x = 1  ###x的作用域为全局作用域,对应全局命名空间

    >>> def foo():
      x = 42 ###x的作用域为局部作用域 ,对应局部命名空间,具体的作用域只在函数体内;局部命名空间中的x指向42
      return x

    >>> x
    1
    >>> foo() ###调用foo函数的时候,局部命名空间就被创建,仅作用于函数内代码块
    42
    >>> x ###调用的全局作用域(全局命名空间)中的x指向的值,所以x=1
    1

    2、Shadowing屏蔽的问题;如果函数体内的局部变量和全局变量的名字相同,在函数体内引用全局变量的话,局部变量会把全局变量屏蔽掉

    >>> def combine(parameter):
        external = 'berry'
        print(parameter+external)

    >>> external = 'Sunshine'
    >>> #想生成'parameter+'Sunshine''

    >>> combine('you are my ')
    you are my berry  ###这个结果并不是我们期待的结果,因为局部变量和全局变量的名字一样,所以局部变量把全局变量屏蔽了

    3、globals()函数,无参数,将获取全局变量的字典类型,使用方法 globals()['全局变量名'] 返回全局变量对应的值;修改上面的函数

    >>> def combine(parameter):
        external = 'berry'
        print(parameter+globals()['external'])

    >>> external = 'Sunshine'
    >>> combine('you are my ')
    you are my Sunshine

    4、函数内重新绑定全局变量(指向新的内容),如果函数有必要改变全局变量,使用global 变量名;用global声明 函数体内的变量为全局变量

    >>> x = 1
    >>> def change_global():
      global x
      x = x+1

    >>> change_global()
    >>> x   
    2

    5、嵌套作用域,一个函数内嵌套了另一个函数,外层函数返回内层函数(内层函数未被调用只是返回);内层函数是可以访问外层函数的变量的,这个就叫嵌套作用域;

    例子:

    >>> def multiplier(factor):
        def multiplyByFactor(number):
          return(number*factor)####外层函数multiplier的变量factor,被内层函数multiplyByFactor引用了
        return multiplyByFactor###外层函数返回内层函数

     类似multiplyByFactor函数,存储于一个封闭的作用域的行为叫做闭包(因为它引用的变量都在函数体内或者外层函数内,如果factor为全局变量,则它就不是闭包)

    查看一个函数是否是闭包用:函数.__closure__

    >>> def multiplier(factor):
        def multiplyByFactor(number):
          return(number*factor)
        print(multiplyByFactor.__closure__)###双下划线
        return multiplyByFactor

    >>> multiplier(2)
    (<cell at 0x000001A961B4AEB8: int object at 0x00007FFE82BBE370>,) ##显示cell说明函数multiplyByFactor是闭包
    <function multiplier.<locals>.multiplyByFactor at 0x000001A961B79F28>###这个返回值只说明multiplier内嵌了函数multiplyByFactor,并不表示multiplyByFactor是闭包

    非闭包嵌套函数

    >>> def multiplier(factor):
        def multiplyByFactor(number):
          return(number*number2)###未引用外层函数的变量
        print(multiplyByFactor.__closure__)
        return multiplyByFactor

    >>> number2 =3
    >>> multiplier(2)
    None  ###说明multiplyByFactor函数不是一个闭包函数,因为它引用的变量是自己的变量和全局变量,未引用外层函数变量
    <function multiplier.<locals>.multiplyByFactor at 0x000001A961B92048>

    >>> def multiplier(factor):
        def multiplyByFactor(number):
          return(number*factor*number2)###引用自身变量、外层函数变量、全局变量也不是闭包
        print(multiplier.__closure__)
        return multiplyByFactor

    >>> number2 =3
    >>> multiplier(2)
    None
    <function multiplier.<locals>.multiplyByFactor at 0x000001A961B79F28>

    nonlocal函数可以使内部函数重新对外层函数变量进行重绑定

    >>> def counter():
        counter = 0
        def do_nonlocal():
          nonlocal counter
          counter+=1
          return counter
        return do_nonlocal

    >>> ct = counter()

    >>> print(ct())

    1
    >>> print(ct())

    2
    >>> print(ct())

    3
    >>> ct = counter()  ###counter=0被重定向为1

    >>> print(ct())

    1

     注意:如果内层函数变量名与外部函数变量名重复,外部函数变量名会覆盖内层函数变量名

    提示:Inspection info: This inspection detects shadowing names defined in outer scopes.

    def scope_test():
        def func_local():
            ##Inspection info: This inspection detects shadowing names defined in outer scopes.
            parameter = 'local parameter'  
    
        def statement_nonlocal():
            nonlocal parameter
            parameter = 'nonlocal parameter'
    
        def statement_global():
            global parameter
            parameter = 'global parameter'
        parameter = 'out scope parameter'
        func_local()
        print('After local assignment:',parameter)
        statement_nonlocal()
        print('After nonlocal assignmet:',parameter)
        statement_global()
        print("After global assignment:",parameter)
    
    if __name__ == '__main__':
        scope_test()
        print('now the parameter is:',parameter)

  • 相关阅读:
    .net中实现运行时从字符串动态创建对象
    C# 用 VB.net 函數庫 實現全角與半角轉換
    實現.net 加載插件方式
    VS2008下載
    Lotus Notes Send EMail from VB or VBA
    用C#写vs插件中的一些Tip
    SQL2005中异常处理消息框可直接使用
    C#路径/文件/目录/I/O常见操作汇总
    利用.net反射动态调用指定程序集的中的方法
    说说今年的计划
  • 原文地址:https://www.cnblogs.com/t-ae/p/10859442.html
Copyright © 2011-2022 走看看