zoukankan      html  css  js  c++  java
  • 可变长参数、函数的嵌套、名称空间和作用域学习笔记

    写在博客的开头

    nick说:人生疾苦唯有自救,这是你相信IT的最后一次机会。这个时候必须得逼自己一把,只有对自己够狠才能慢慢强大。昨天看一哥们在博客上说每天大喊一遍python第一java第二,python大法无所不能,给自己以一个乐观积极的态度好好学习天天向上。加油,希望我们每一个人都不负光阴。

    可变长参数

    *形参名

    def f1(*args):#调用时有多少个位置实参就接收多少个
        print(args)#*args(约定俗成的),用元组接收多余的位置实参
    

    **形参

    def f1(**kwargs):
        print(kwargs)#用字典接收多余的关键字实参
    

    以上内容很important,以下内容仅作了解(Nick说以后很少用到)

    *实参

    def f1(a,b,c,d,e,f,g):
        print(a,b,c,d,e,f,g)
        
        lt = [1,2,3,4,5,6,7]
        f1[*lt]#*lt把列表中的元素打散成位置实参一次传给位置形参(这个过程其实就是解压缩)
    

    **实参

    def f1(z,b):
        print(z,b)
    dic = {'z':,'b':2}
    f1(**dic)#**dic把字典打散成关键字实参然后传给函数f1
    

    函数对象

    Python中一切皆对象,函数是第一类对象,即函数可以被当作数据处理。

    def func():
        print('from func')
        
    prnit(func)
    

    <function func at 0x10af72f28>

    一、函数对象的四大功能

    1. 引用

      x = 'hello nick'
      y = x
      
      f = func#这么做的的原因是:这样f()和func()就是同一个函数了
      print(f)
      

      <function func at 0x10af72f28>

    2. 当做参数传给一个函数

      len(x)
      
      def foo(m):
          m()
      foo(func)#func是一个函数名,将func作为实参传给foo这个函数,形参m用于接收func,执行到foo函数体里面就得到了func()实现了对func函数的调用。 
      

      from func

    3. 可以当做函数的返回值

      def foo(x):
          return x
      
      res = foo(func)
      print(res)
      res()#func被return回来赋给res从而实现了对func函数的调用
      

      <function func at 0x10af72f28>
      from func

    4. 可以当作容器类型的元素

      l = [x]
      
      function_list = [func]
      function_list[0]()#这个就很叼了,在调用登录注册等多个函数时把函数名作为字典的value,然后通过这种方法去调用函数贼方便。
      

      from func

    练习

    def register():
        print('register')
    def login():
        pass
    def withdraw():
        pass
    def shoppong():
        print('shopping')
    func_dict = {
        '1':register,
        '2':login,
        '3':withdraw,
        '4':shopping,
    }
    print('''
    1 注册
    2 登录
    3 提现
    4 购物
    ''')
    while Ture:
        choice = input('请选择你需要的功能(输入q退出):')
        if choice == 'q':
            break
         func_dict[choice]()#函数当做容器类型的元素
        
    

    函数的嵌套

    所谓嵌套就是在函数内部再定义函数,不过函数内部定义的函数,无法在函数外部使用。

    def f1():
        def f2():
            print('from f2')
        f2()
    
    f2()  
    # NameError: name 'f2' is not defined
    

    这个就可以使用:

    def f1():
        def f2():
            print('from f2')
        f2()
    
    f1()
    

    from f2

    函数嵌套的调用

    如下面一个比较四个数大小得出最大值的函数

    def compare_1(x,y):
        if x>y:
            return x
        else:
            return y
    def compare_2(a,b,c,d):
        res1 = compare_1(a,b)
        res2 = compare_1(res1,c)
        res3 = compare_1(res2,d)#牛掰哦这种比较方法
            return res3
    #compare_2(1,2,3,4)
    print(compare_2(1,2,3,4))
    

    4

    名称空间和作用域

    一、名称空间

    名称空间(name spaces):在内存管理那一章节时,我们曾说到变量的创建其实就是在内存中开辟了一个新的空间。但是我们一直在回避变量名的存储,其实在内存中有一块内存存储变量名与变量间的绑定关系的空间,而这个空间称为名称空间。

    1.1 内置名称空间

    内置名称空间:存放Pyhton解释器自带的名字,如int、float、len

    生命周期:在解释器启动时生效,在解释器关闭时失效。

    1.2 全局名称空间

    全局名称空间:除了内置和局部的名字之外,其余都存放在全局名称空间。

    生命周期:在文件执行时生效,在文件执行结束后失效。

    1.3 局部名称空间

    局部名称空间:用于存放函数调用期间函数体产生的名字,如下面代码的f2

    生命周期:在文件执行时函数调用期间时生效,在函数执行结束后失效。

    def f1():
        def f2():
            print('from f2')
        f2()
    f1()
    

    1.4 加载顺序

    由于.py文件是由Python解释器打开的,因此一定是在Python解释器中的内置名称空间加载结束后,文件才开始打开,这个时候才会产生全局名称空间,当文件内某一个函数被调用时,才会产生局部名称空间,因此名称空间的加载顺序为:内置》全局》局部》。

    1.5 查找顺序

    由于名称空间是用来存放变量名与变量值之间的绑定关系的,所以但凡要查找名字,一定要从三者之一找到,查找顺序为:

    从当前所在的位置开始查找,如果当前所在的位置为局部名称空间,则查找顺序为:局部》全局》内置。

    x = 1
    y = 2
    len = 100
    
    def func():
        y = 3
        len = 1000
        print(f"y:{y}")
        print(f"len:{len}")
       
    func()    
    

    y: 3
    len: 1000

    def func():
        
        printx
    x = 10
    func()
    

    10

    二、作用域

    域指的是区域,作用域就是作用的区域。

    2.1 全局作用域

    全局作用域:全局有效,全局存活,包含内置名称空间和全局名称空间。

    #全局作用域
    x = 1
    def bar():
        print(x)
    bar()
    

    1

    2.2 局部作用域

    局部作用域只包含局部名称空间。

    def f1():
        def f2():
            def f3():
                print(x)
            x = 2
            f3()
        f2()
    f1()
    
    

    2

    2.3 注意点

    作用域关系在函数作用阶段就固定死了,与函数的调用无关。

    # 作用域注意点
    x = 1
    
    
    def f1():  # 定义阶段x=1
        print(x)
    
    
    def f2():
        x = 2
        f1()
    
    f2()
    

    1

    很绕的一个例子,画个图看一下:

    程序运行的时候内存空间的开辟如图所示,所以当f1()运行的时候,程序会先在f1()的局部作用域内找x的值,找不到就去全局找而不是去f2()的作用域内找。再看下面一个例子:

    x = 1
    def f2():
        x = 2
    
        def f1():  # 定义阶段x=1
            print(x)
        f1()
    f2()
    

    2

    这个f1执行完就回去f2找x的值,因为f1的作用域在f2里面。

    2.4 函数对象+作用域应用

    # 作用域应用
    def f1():
        def inner():
            print('from inner')
        return inner
    
    f = f1()  # 把局部定义的函数放在全局之中
    
    def bar():
        f()
    
    bar()#相当于f1()(),相当于inner()
    

    from inner

    三、补充知识点

    3.1 global关键字(尽量少用,Nick说容易懵逼)

    修改全局作用域中的变量。

    x = 1
    
    
    def f1():
        x = 2
    
        def f2():
            #         global x  # 修改全局
            x = 3
        f2()
    
    
    f1()
    print(x)
    

    1

    x = 1
    
    
    def f1():
        x = 2
    
        def f2():
            global x  # 修改全局
            x = 3
        f2()
    
    
    f1()
    print(x)
    

    3

    3.2 nonlocal关键字(最好不要使用,容易把自己弄懵逼)

    修改作用域中的变量。

    x = 1
    
    
    def f1():
        x = 2
    
        def f2():
            #         nonlocal x
            x = 3
    
        f2()
        print(x)
    
    
    f1()
    

    2

    x = 1
    
    
    def f1():
        x = 2
    
        def f2():
            nonlocal x
            x = 3
    
        f2()
        print(x)
    
    
    f1()
    

    3

    3.3 注意点(very important)

    1. 可变数据类型可以打破上述一切规则。
    lt = [10]
    
    
    def f1():
        lt.append(12)
        lt[0] = 11
    
    
    f1()
    
    print(lt)
    

    [11, 12]

    1. 在局部如果想修改全局的不可变类型,需要借助global声明,声明为全局变量,即可直接修改。
  • 相关阅读:
    使用DirectX作渲染过程
    记于来北京两个星期
    添加 node mocha 测试模块
    for-of循环
    app-web 开发 追溯debug
    cmd关闭被占用的端口命令及教程详解
    vue使用element-ui的el-input监听不了键盘事件解决
    Nodejs 进阶:Express 常用中间件 body-parser 实现解析
    nodejs设置允许跨域
    nodejs 全局变量和全局对象
  • 原文地址:https://www.cnblogs.com/ghylpb/p/11559985.html
Copyright © 2011-2022 走看看