zoukankan      html  css  js  c++  java
  • 函数的进阶

    主要内容

    • 1. 函数参数--动态传参
    • 2. 名称空间, 局部名称空间, 全局名称空间, 作用域, 加载顺序.
    • 3. 函数的嵌套
    • 4. gloabal, nonlocal关键字

    1.函数参数--动态传参

    • 要给一个函数传参, 而参数又是不确定的.
    • 给一个函数传很多参数, 形参就要写很多,避免麻烦可以考虑使用动态参数

         (1) 动态接收位置参数 - *args

    def star(*name):
        print(name,"演技可以")
    star("周星驰","陈道明","黄渤","徐峥")
    结果:
    ('周星驰', '陈道明', '黄渤', '徐峥') 演技可以

         若形参含有位置参数,*args必须在位置参数后面

    def star(*name,a,b):
        print(name,a,b,"演技可以")
    star("周星驰","陈道明","黄渤","徐峥")
    #会报错
    #TypeError: star() missing 2 required keyword-only arguments: 'a' and 'b',此时的a&b永远接收不到数据

             修改:

    def star(*name,a,b):
        print(name,a,b,"演技可以")
    star("周星驰","陈道明",a="黄渤",b="徐峥")  # 此时必须用关键字去指定
    结果:

    ('周星驰', '陈道明') 黄渤 徐峥 演技可以

    #先写位置参数, 然后再用动态参数
    def star(a,b,*name):
        print(a,b,name,"演技可以")
    star("周星驰","陈道明","黄渤","徐峥")
    #周星驰 陈道明 ('黄渤', '徐峥') 演技可以

            当使用默认参数

    def star(a,b,c="李连杰",*name):
        print(a,b,c,name,"演技可以")
    star("周星驰", "陈道明")                         #周星驰 陈道明 李连杰 () 演技可以    #默认值生效
    star("周星驰","陈道明","黄渤")                    #周星驰 陈道明 黄渤 () 演技可以      #默认值不生效
    star("周星驰","陈道明","黄渤","徐峥")              #周星驰 陈道明 黄渤 ('徐峥',) 演技可以   #默认值不生效

    默认值参数写在*args前面,默认值只有⼀种情况可能会生效. 

    def star(a,b,*name,c="李连杰"):
        print(a,b,name,c,"演技可以")
    star("周星驰", "陈道明")                         #周星驰 陈道明 () 李连杰 演技可以    #默认值效
    star("周星驰","陈道明","黄渤")                    #周星驰 陈道明 ('黄渤',) 李连杰 演技可以   #默认值生效
    star("周星驰","陈道明","黄渤","徐峥")              #周星驰 陈道明 ('黄渤', '徐峥') 李连杰 演技可以  #默认值生效

            这个时候我们发现所有的默认值都生效了. 这个时候如果不给出关键字传参. 那么你的默认值是永远都生效的

            顺序: 位置参数,*args, 默认值参数

         (2) 动态接收关键字参数 - **kwargs

    def func(**kwargs):
        print(kwargs)
    func(a=1, b=2, c=3)  # {'a': 1, 'b': 2, 'c': 3} 
    func(a=1, b=2)      # {'a': 1, 'b': 2}                       #接收到的是一个字典
    •  在函数调用的时候, 关键字参数必须在位置参数后面. 由于实参是这个顺序. 所以形参接收的时候也是这个顺序.
    •  位置参数必须在关键字参数前面. 动态接收关键字参数也要在后面 
    •   最终顺序(*): 位置参数  -- *args --  默认值参数  -- **kwargs

    如果想接收所有的参数:

    def func(*args, **kwargs):
        print(args, kwargs)
    func("麻花藤","⻢马晕",wtf="胡辣汤")           #('麻花藤', '⻢马晕') {'wtf': '胡辣汤'}   

        (3)动态参数的另外一种传参方式

    def func(*args):        # 在这里. 其实相当于把传进来的参数做了一次聚合, 聚合成一个元组
        print(args)
    lst = [1, 4, 7]
    a ="倚天屠龙记"
    func(*lst)           # (1, 4, 7)         在实参位置 * 表示打散, 打散的是可迭代对象
    func(*a)            #('倚', '天', '屠', '龙', '记')

      如果是⼀个字典, 那么也可以打散. 不过需要用两个* 

    def fun(**kwargs):
        print(kwargs)
    dic = {'a':1, 'b':2}
    fun(**dic)
    def func(**kwargs):                 # ** 把接收到的关键字参数打包(聚合)成字典
        print(kwargs)                   # 一定是字典
    dic = {"张无忌": "明教教主", "谢逊": "金毛狮王", "范瑶": "光明右使"}
    func(张无忌=dic['张无忌'], 谢逊=dic['谢逊'], 范瑶=dic['范瑶'])
    func(**dic)                         # 这里的** 是把字典打散. 字典的key作为参数的名字, 字典的值作为参数的值传递给形参

    小结:

          (1) 位置参数

          (2) 默认值参数 

          (3)动态参数

    • *args 位置参数的动态传参. 系统会自动的把所有的位置参数聚合成元组
    • **kwargs 关键字的动态传参. 系统会自动把所有的关键字参数聚合成字典
    • def func(*args, **kwargs): 无敌传参
    • 顺序: 位置参数, *args, 默认值, **kwargs
    • 在使用的时候, 可以任意的进行搭配

          (4)在实参上. *, **表示的打散. 在形参. *,** 表示聚合

    2. 名称空间, 局部名称空间, 全局名称空间, 作用域, 加载顺序.

    • 在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量量的时候, 就 把变量量名和值之间的关系记录下来,
    • 当遇到函数定义的时候, 解释器只是把函数名读入内存, 表示这个函数存在了,  至于函数内部的变量和逻辑, 解释器是不关心的.
    • 一开始的时候函数只是加载进来, 仅此而已, 只有当函数被调用和访问的时候, 解释器才会根据函数内部声明的变量来进行开辟变量的内部空间.
    • 函数执行完毕, 这些函数内部变量占用的空间也会随着函数执行完毕而被清空

    (1)命名空间 :存放名字和值的关系的空间,变量在存储的时候就是存储在这片空间中的.     

    • 全局命名空间-- 直接在py文件中, 函数外声明的变量都属于全局命名空间       
    • 局部命名空间-- 在函数中声明的变量会放在局部命名空间       
    • 内置命名空间-- 存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置命名空间

    (2)加载顺序&取值顺序:

    • 加载顺序:  内置命名空间>全局命名空间 >局部命名空间(函数被执行的时候)
    • 取值顺序:  局部命名空间 >全局命名空间 >内置命名空间

    (3)作用域  就是作用范围, 按照生效范围来看分为全局作用域和局部作用域     

    •  全局作用域:    全局命名空间 + 内置命名空间       通过globals()函数来查看全局作用域中的内容
    •  局部作用域:    局部命名空间                                 通过locals()来查看局部作用域中的变量和函数信息 
    a = 10
    def func():
        a = 40
        b = 20
        def abc():
            print("哈哈")
            print(a, b)         # 这里使用的是局部作用域
            print(globals())    # 打印全局作用域中的内容
            print(locals())     # 打印局部作用域中的内容
        abc()
    func()

    3.函数的嵌套

    • 只要遇见了()就是函数的调用. 如果没有()就不是函数的调用 
    • 函数的执行顺序
    def fun1():
        print(111)
    def fun2():
        print(222)
        fun1()
    fun2()
    print(111)
    
    # 函数的嵌套
    def fun2():
        print(222)
        def fun3():
            print(666)
        print(444)
        fun3()
        print(888)
    print(33)
    fun2()
    print(555)

    4. gloabal, nonlocal关键字

      global表示不再使用局部作用域中的内容了,而改用全局作用域中的变量

    a = 10
    def func():
        global a       #表示在当前作用域中的使用的a是全局中的变量
        a = 20         # 所有的a都是外面的了
        print(a)      # 现在只有看的权利
    print(a)    # 10
    func()     # 20
    print(a)  # 20

     nonlocal 表示在局部作用域中, 调用离他最近的上层的那个变量

    def outer():
        a = 10
        def inner():
            nonlocal a # 找的是局部当中, 离他最近的上层的那个变量
            a = 20
            print(a)
        print(a)      # 10
        inner()      # 20
        print(a)    # 20
    outer()

    练习;

    a = 1
    def fun_1():
        a = 2
        def fun_2():
            nonlocal a
            a = 3
            def fun_3():
                a = 4
                print(a)
            print(a)
            fun_3()
            print(a)
        print(a)
        fun_2()
        print(a)
    print(a)
    fun_1()
    print(a)            #1234331

     Homework

    1.写函数,接收n个数字,求这些参数数字的和。

    def func(*n):
        sum = 0
        for el in n:
            sum += el
        return sum
    ret = func(1,2,5,4,7)

    2.写函数,传入函数中多个实参(均为可迭代对象如字符串,列表,元祖,集合等),将每个实参的每个元素依次添加到函数的动态参数args里面.

    例如 传入函数两个参数[1,2,3] (22,33)最终args为(1,2,3,22,33)

    def func(*args): # str, list, tuple, set
        print(args)
        # lst = []
        # for el in args:
        #     for e in el:
        #         lst.append(e)
        # tu = tuple(lst)
        # print(tu)
    func(*[1,2,3], *(22,33))

    3.写函数,传入函数中多个实参(实参均为字典),将每个实参的键值对依次添加到函数的动态参数kwargs里面.

      例如 传入函数两个参数{‘name’:’alex’} {‘age’:1000}最终kwargs为{‘name’:’alex’ ,‘age’:1000}

    def func(*args):
        print(args)
    func(*[1,2,3],*(22,33))
    6
    def func(**kwargs):
        print(kwargs)
    func(**{"name":"alex"},**{"age":1000})

    4.写函数,接收两个数字参数,将较小的数字返回.

    def min_func(a,b):
        c = a if a < b else b
        return c

    5.写函数,接收一个参数(此参数类型必须是可迭代对象),将可迭代对象的每个元素以’_’相连接,形成新的字符串,并返回.

    例如 传入的可迭代对象为[1,'老男孩','武sir']返回的结果为’1_老男孩_武sir’

    def func(*args):
        lst = []
        for el in args:
            lst.append(str(el))
            s = '_'.join(lst)
        return s
    print(func(*[1,'老男孩','武sir']))
    def func(*args):
        s =""
        for el in args:
            s = s+str(el)+"_"
        return s[:-1]
    print(func(*[1,'老男孩','武sir']))

    6.写函数,传入n个数,返回字典{‘max’:最大值,’min’:最小值}, 例如:min_max(2,5,7,8,4) 返回:{‘max’:8,’min’:2}(此题用到max(),min()内置函数)

    def min_max(*args):
        return({"max":max(args),"min":min(args)})
    print( min_max(2,5,8,7))

    7.写函数,传入一个参数n,返回n的阶乘    例如:cal(7)  计算7*6*5*4*3*2*1

    def cal(n):
        a = 1
        for i in range(1,n+1):
            a = a*i
        return a
    print (cal(7))
    def func(n):
        sum = 1
        for i in range(n, 0, -1):
            sum *= i
        return sum
    print(func(5))

    8.写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组

    例如:[(‘红心’,2),(‘草花’,2), …(‘黑桃’,‘A’)]

    def func():
        H = ["红心","黑桃","梅花","方块"]
        D = ["A","2","3","4","5","6","7","8","9","10", "J", "Q", "K"]
        result=[]
        for h in H:
            for d in D:
                result.append((h,d))
        return result
    print(func())

    9.相关面试题(先从纸上写好答案,然后在运行)

       (1)有函数定义如下:

    def calc(a,b,c,d=1,e=2):

    return (a+b)*(c-d)+e

    请分别写出下列标号代码的输出结果,如果出错请写出Error。

    • print(calc(1,2,3,4,5))_____
    • print(calc(1,2))____
    • print(calc(e=4,c=5,a=2,b=3))___
    • print(calc(1,2,3))_____
    • print(calc(1,2,3,e=4))____
    • print(calc(1,2,3,d=5,4))_____ 

      (2)(此题有坑)下面代码打印的结果分别是_________,________,________.

      def extendList(val,list=[]):
              list.append(val)
              return list
           list1 = extendList(10)
           list2 = extendList(123,[])
           list3 = extendList('a')

           print('list1=%s'%list1)
           print('list2=%s'%list2)
           print('list3=%s'%list3)

      

  • 相关阅读:
    Intent
    What should we do next in general after collecting relevant data
    NOTE FOR Secure Friend Discovery in Mobile Social Networks
    missing pcap.h
    after building Android Source code
    plot point(one column)
    When talking to someone else, don't infer that is has been talked with others at first. It may bring repulsion to the person who is talking with you.
    进程基本知识
    Python input和raw_input的区别
    强制 code review:reviewboard+svn 的方案
  • 原文地址:https://www.cnblogs.com/wcx666/p/9646593.html
Copyright © 2011-2022 走看看