名称空间与作用域

名称空间

  • 当你定义一个num = 123时,123存放在内存中,那num变量名存放在哪里呢?答案就是名称空间,名称空间就是用来存放名字的地方。

    • 名称空间分类:

      • 内置名称空间

        • 启动python解释器的时候加载内置名称空间

      • 全局名称空间

        • 执行py脚本的时候加载全部名称空间

      • 局部名称空间

        • 执行到函数的时候加载函数内部的名称空间,成为局部名称空间

    • 函数的查找方式

      • 当执行一个函数的时候,首先会在当前所在的名称空间查找,如果找不到会继续向外找

        >>> def max():
        ...     print('from max')
        ...
        >>> def func():
        ...     def max():
        ...         print('from func.max')
        ...     max()
        ...
        >>> func()  # 执行func的时候首先在函数体内部寻找,如果有则打印内部的
        from func.max
        ​
        >>> max()   # 这调用max会执行什么呢?肯定是 from max,因为查找顺序一定是从当前名称空间查找,如果全局没有则会去查找内置的,而不会去查找局部的了
        >>> del max
        >>> max # 查找内置名称空间的函数
        <built-in function max>>>> def func(): # 函数体内部没有max,则从当前向外查找
        ...     max()
        ...
        >>> func()
        from max

函数嵌套

  • 函数嵌套就是在函数体的内部定义函数,嵌套多层

    >>> def func():
    ...     def func1():
    ...         def func2():
    ...             print('from func2')
    ...         func2()
    ...     func1()
    ...
    >>> func()
    from func2
    >>> func1()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'func1' is not defined
    # 调用func1() 为什么会报错呢?这就用到了作用域

作用域

  • 作用域分为两种

    • 全局作用域

      • 全局名称空间

      • 内置名称空间

    • 局部作用域

      • 局部名称空间

  • 什么是作用域呢?

    • 作用域用到了里、外的概念,我在里面操作的是我自己的不会操作外面的,而在外面操作的同理

      >>> num = 123
      >>> def func():
      ...     num = 456
      ...     print(num)
      ...
      >>> func()  # 调用函数体内部的num
      456
      >>> num # 调用全局的num
      123
      # 无论在func函数体内怎么操作,都不会影响外部的num变量
      >>> num = 11111111  # 修改的是全局的num
      >>> num
      11111111
      >>> func()  # 不影响函数内部
      456# 如果理解了作用域的概念,来解读一下函数嵌套提到的问题,举个例子
      >>> del num # 将全局的num变量删除
      >>> num # 此时调用num变量,会输出456吗? 是不会的
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      NameError: name 'num' is not defined
          
      # 为什么调用不到呢?还记得之前我说过,在外面也就是全局操作是不会应用到函数体内部的
          当前例子查找流程:
              全部查找num找不到 --> 内置空间查找还是找不到 --> 报错
              不会去函数内部去查找局部的了
              
      总结:
      一定要记住,查找顺序是从当前空间查找,找不到就会向外查找,而不会像内查找

       

  • global与nolocal关键字

    • 如果一定要在函数内部修改局部的变量呢?这就用到了global关键字

      >>> num = 123
      >>> def func():
      ...     global num  # 声明要修改的是全局的
      ...     num = 456
      ...
      >>> func()
      456
      # 不推荐使用,这样会污染外部的变量,应该做到内外互不干扰
    • 那么nolocal关键字是干嘛的呢?

      • 修改函数体内部上层嵌套函数体定义的变量

        >>> num = 123
        >>> def func(): # 如果在这(最外部函数体)找不到就会报错,而不会去寻找全局
        ...     num = 456
        ...     def func1():
        ...         num = 789   # 本例,在这找到了,如果在这找不到则会去找func里面的num
        ...         def func2():
        ...             nonlocal num    # 声明修改上层变量
        ...             num = 111111
        ...             print(num)
        ...         func2()
        ...         print(num)
        ...     func1()
        ...     print(num)
        ...
        >>> func()
        111111
        111111
        456
        >>> num
        123
        ​
        总结:
            从下向上一层一层函数体寻找,找到则修改不继续寻找,找不到则一直找,查找到最外层函数体还是没找到就会报错,不会去查找全局
posted @ 2018-11-11 16:47  浩小白  Views(104)  Comments(0Edit  收藏  举报