python3 namespace_scope 命名空间和作用域.py

"""
Python3 命名空间和作用域。
模块:python3 namespace_scope 命名空间和作用域.py
参考:https://www.runoob.com/python3/python3-namespace-scope.html
知识点:
    1.命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。
    2.一般有三种命名空间:
        内置名称(built-in names), Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
        全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
        局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)
    3.命名空间查找顺序:
        假设我们要使用变量 runoob,则 Python 的查找顺序为:局部的命名空间去 -> 全局命名空间 -> 内置命名空间。
        如果找不到变量 runoob,它将放弃查找并引发一个 NameError 异常:
        NameError: name 'runoob' is not defined。
    4.命名空间的生命周期:
        命名空间的生命周期取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束。
        因此,我们无法从外部命名空间访问内部命名空间的对象。
    5.Python 的作用域一共有 4 种,分别是:
        L(Local):最内层,包含局部变量,比如一个函数/方法内部。
        E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。
            比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,
            那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
        G(Global):当前脚本的最外层,比如当前模块的全局变量。
        B(Built-in):包含了内建的变量/关键字等,最后被搜索。
        规则顺序: L –> E –> G –> B。
        在局部找不到,便会自动去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。
    6.在局部作用域,想要访问(CRUD)全局作用域、包围作用域的变量有 3 种方式:
        1.传参。
        2.使用 global var(提前声明,访问全局作用域), nonlocal var(提前声明,访问紧挨着的包围作用域)。
        3.在当前作用域中,没有该变量,会自动、顺序地去更大的域中寻找,直到找到。
            或者,报错 NameError: name 'var' is not defined。
            这种情况下,不可变类型,比如:字符串,数字,元组,可读,不可改变
           (提前使用 global, nonlocal 声明,这种情况可以解除)。
            可变类型,如:列表,字典,集合,可读,可改。
    7.
"""
import builtins
import pprint

# 1.查看 内建变量。
# help(builtins)
# pprint.pprint(dir(builtins))
# print(dir(builtins))
# ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError',
#  'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError',
#  'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
#  'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError',
#  'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError',
#  'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
#  'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError',
#  'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
#  'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning',
#  'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning',
#  'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError',
#  'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
#  'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError',
#  'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError',
#  'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__',
#  '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint',
#  'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
#  'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format',
#  'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance',
#  'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next',
#  'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed',
#  'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod',
#  'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

# 2.全局变量。
var1 = 5


def some_func():
    # 3.包围变量(Enclosing)。
    var2 = 6

    def some_inner_func():
        # 4.局部变量。
        var3 = 7


# 5.Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,
#   其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,
#   也就是说这些语句内定义的变量,外部也可以访问。
if True:
    msg = 'I am from Runoob.'
print("\n5.")
print(msg)  # I am from Runoob.

# 6.全局变量和局部变量
#   定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。
#   局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。
#   在函数内,访问全局变量时,需要提前声明,如:global var, var...
#   调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。如下实例:
print("\n6.")
total = 0  # 这是一个全局变量


# 函数说明
def my_sum(arg1, arg2):
    """
    求两个数的和。
    :param arg1:
    :param arg2:
    :return:
    """
    total = arg1 + arg2  # total在这里是局部变量.
    print("局部 total:", total)
    return total


my_sum(10, 20)
print("全局 total:", total)
# 局部 total: 30
# 全局 total: 0

# 7.global 和 nonlocal关键字
#   当内部作用域访问外部作用域的变量时,就要用到 global和 nonlocal 关键字了。
num = 1


def fun1():
    global num  # 需要使用 global 关键字声明
    print(num)
    num = 123
    print(num)


print("\n7.")
fun1()
print(num)


# 1
# 123
# 123

# 7.2.如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量,则需要 nonlocal 关键字了。
def outer():
    num = 10

    def inner():
        nonlocal num  # nonlocal关键字声明
        num = 100
        print(num)

    inner()
    print(num)


print("\n7.2.")
outer()
# 100
# 100

# 7.3.函数参数的绑定关系。
# 变量不是对象,变量用于绑定对象,变量和对象之间的关系称为绑定(引用)关系。
# 把数字对象 10 赋值给 a, 那么 a 就绑定(引用)了 数字对象 10。
# 函数的参数是局部变量。
a = 10


def test(a):
    # a = a + 1
    # a += 1
    a = 1
    print(a)
    print(locals())  # {'a': 1}


print("\n7.3.")
test(a)
print(a)
# 1
# 10

# 8.在局部、包围、全局作用域,可以直接访问内建作用域的变量,不用提前声明。
#   以 str(), type() 内建变量为例。
print("\n8.")
n = 10
s = str(n)
print(s, type(s))


# 10 <class 'str'>

# 8.2.
def f():
    n = 10
    s = str(n)
    print(s, type(s))


f()  # 10 <class 'str'>


# 8.3.
def f():
    n = 10
    s = str(n)
    print(s, type(s))

    def f():
        pass


f()  # 10 <class 'str'>

# 9.在当前作用域中,没有该变量,会自动、顺序地去更大的域中寻找,直到找到。
#   或者,报错 NameError: name 'var' is not defined。
#   这种情况下,不可变类型,比如:字符串,数字,元组,可读,不可改变
#  (提前使用 global, nonlocal 声明,这种情况可以解除)。
#   可变类型,如:列表,字典,集合,可读,可改。

i = 0
i += 1
# del i
list1 = [0, 1]


def fun1():
    # global i  # 使用 global i 声明,可以解除,不可变类型不能直接改的情况。
    # i += 1  # 不能改。
    # i = i + 1  # 同上
    print(i)  # 不可变类型,可以直接读,但是不能改,如上操作。
    list1.append(i)  # 可变类型,可读可改。
    print(list1)
    print(locals())


print("\n9.")
fun1()
print(list1)
# 1
# [0, 1, 1]
# {}
# [0, 1, 1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值