zoukankan      html  css  js  c++  java
  • python函数(二)

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

      之前我们说过了传参,如果我们需要给一个函数传参,而参数又是不确定的,或者我给一个函数传很多参数,我的形参就要写很多,很麻烦,怎么办呢.我们可以考虑使用动态参数.

      形参的第三种:动态参数

      动态参数分成两种:

      1.动态的接收位置参数

      首先我们先回顾下位置参数,位置参数,按照位进行传参  

    1 def chi(quality_food, junk_food):
    2     print("我要吃", quality_food, junk_food)
    3 chi("大米饭", "小米饭") # "大米饭"传递给quality_food "小米饭"传递给junk_food
    4 按照位置传

       现在问题来了.我想吃任意的食物,数量是任意的,食物也是任意的.这时我们就要用到动态参数了.

     在参数位置编写*表示接收任意内容

    1 def chi(*food):
    2  print("我要吃", food)
    3 chi("大米饭", "小米饭")
    4 结果:
    5 我要吃 ('大米饭', '小米饭') # 多个参数传递进去,收到的内容是元组tuple

    动态接收参数的时候要注意:动态参数必须在位置参数后面

    1 def chi(*food, a, b):
    2   print("我要吃", food, a, b)
    3 chi("大米饭" "小米饭" "黄瓜" "茄子")

    这时候程序运行会报错.因为前面传递进去的所有位置参数都被*food接收了.a和b永远接收不到参数

    所以必须改写成下面的代码

    1 def chi(*food, a, b):
    2  print("我要吃", food, a, b)
    3 chi("大米饭", "小米饭", a="黄瓜", b="茄子") # 必须用关键字参数来指定

    这个时候a和b就有值了,但是这样写位置参数就不能用了,所以我们要先写位置参数,然后再用动态参数

    1 def chi(a, b, *food):
    2   print("我要吃", a, b, food)
    3 chi("大米饭", "小米饭", "馒头", "面条") # 前两个参数⽤位置参数来接收,后面的参数用动态参数接收

    默认参数

    1 def chi(a, b, c='馒头', *food):
    2   print(a, b, c, food)
    3 
    4 chi("香蕉", "菠萝") # 香蕉 菠萝 馒头 (). 默认值生效
    5 chi("香蕉", "菠萝", "葫芦娃") # 香蕉 菠萝 葫芦娃 () 默认值不生效
    6 chi("香蕉", "菠萝", "葫芦娃", "口罩") # 香蕉 菠萝 葫芦娃 ('口罩',) 默认值不生效
    7  

    我们发现默认参数写在动态参数前面.默认值只有一种情况可能会生效.

    1 def chi(a, b, *food, c="娃哈哈"):
    2   print(a, b, food, c)
    3 
    4 chi("香蕉", "菠萝") # 香蕉 菠萝 () 娃哈哈 默认值生效
    5 chi("香蕉", "菠萝", "葫芦娃") # 香蕉 菠萝 ('葫芦娃',) 娃哈哈 默认值生效
    6 chi("香蕉", "菠萝", "葫芦娃", "口罩") # 香蕉 菠萝 ('葫芦娃', '口罩') 娃哈哈 默认值生效

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

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

    2.动态接收关键字参数

    在python中可以动态的位置参数,但是*这种情况只能接收位置参数无法接收关键字参数.

    在python中使用**来接收动态关键字参数

    1 def func(**kwargs):
    2   print(kwargs)
    3 func(a=1, b=2, c=3)
    4 func(a=1, b=2)
    5 结果:
    6 {'a': 1, 'b': 2, 'c': 3}
    7 {'a': 1 'b': 2}

    这个时候接收的是一个dict

    顺序的问题,在函数调用的时候,如果先给出关键字参数,则整个参数列表会报错

    1 def func(a, b, c, d):
    2   print(a, b, c, d)
    3 # 关键字参数必须在位置参数后⾯, 否则参数会混乱
    4 func(1, 2, c=3, 4)

    所以关键字参数必须在位置参数后面,由于实参是这个顺序.所以形参接收的时候也是这个顺序,也就是说位置参数必须在关键字参数前面,动态接收关键字参数也要在后面

    最终顺序:

    位置参数>*args>默认值参数>**kwargs

    这四种参数可以任意的进行使用.

    如果想接收所有的参数:

    1 def func(*args, **kwargs):
    2   print(args, kwargs)
    3 func("麻花藤","马云",wtf="胡辣汤")

     动态参数的另一种传参方式(打散):

    1 def fun(*args):
    2   print(args)
    3 lst = [1, 4, 7]
    4 fun(lst[0], lst[1], lst[2])
    5 fun(*lst) # 可以使用*把一个列表按顺序打散
    6 s = "臣妾做不到"
    7 fun(*s)  字符串也可以打散 (可迭代对象)

    在实参位置上给一个序列,列表,可迭代对象前面加个*表示把这个序列按顺序打散.

    在形参位置上的*表示把接收到的参数组合成一个元组

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

    1 def fun(**kwargs):
    2   print(kwargs)
    3 dic = {'a':1, 'b':2}
    4 fun(**dic)

    函数的注释

    1 def chi(food, drink):
    2   """ 这里是函数的注释, 先写一下当前这个函数是干什么的, 比如我这个函数就是一个吃
    3 :param :param food: 参数food是什么意思
    4  :param :param drink: 参数drink是什么意思
    5  :return :return: 返回的是什么东东
    6   """
    7   print(food, drink)
    8   return "very good"

    二.命名空间

    我们首先回忆一下Python代码运行的时候遇到函数是怎么做的,从Python解释器开始执行之后,就在内存中开辟里一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征性的将函数名读如内存,表示知道这个函数存在了,至于函数内部的变量和逻辑,解释器根本不关心。

      等执行到函数调用的时候,Python解释器会再开辟一块内存来储存这个函数里面的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量回储存在新开辟出来的内存中,函数中的变量只能在函数内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。

    我们给这个‘存放名字与值的关系’的空间起了一个名字-------命名空间。

    命名空间一共分为三种:

      全局命名空间

      局部命名空间

      内置命名空间

    *内置命名空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。

    三种命名空间之间的加载与取值顺序:

    加载顺序:内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

    取值顺序:

      在局部调用:局部命名空间->全局命名空间->内置命名空间

      在全局调用:全局命名空间->内置命名空间

    综上所述,在找寻变量时,从小范围,一层一层到大范围去找寻。

    作用域

    作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。

    全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效

    局部作用域:局部名称空间,只能在局部范围生效

    global关键字,nonlocal关键字。

    global:

      1,声明一个全局变量。

      2,在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)。

     1 def func():
     2     global a
     3     a = 3
     4 func()
     5 print(a)
     6 
     7 
     8 count = 1
     9 def search():
    10     global count
    11     count = 2
    12 search()
    13 print(count)
    14 
    15 global关键字举例

     ps:对可变数据类型(list,dict,set)可以直接引用不用通过global。

     1 li = [1,2,3]
     2 dic = {'a':'b'}
     3 
     4 def change():
     5     li.append('a')
     6     dic['q'] = 'g'
     7     print(dic)
     8     print(li)
     9 change()
    10 print(li)
    11 print(dic)
    12 
    13 对于可变数据类型的应用举例

    nonlocal:

      1,不能修改全局变量。

      2,在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。

     1 def add_b():
     2     b = 42
     3     def do_global():
     4         b = 10
     5         print(b)
     6         def dd_nonlocal():
     7             nonlocal b
     8             b = b + 20
     9             print(b)
    10         dd_nonlocal()
    11         print(b)
    12     do_global()
    13     print(b)
    14 add_b()
    15 
    16 nonlocal关键字举例

    三.函数的嵌套

      1.只要是遇见了()就是函数的调用.如果没有()就不是函数的调用

      2.函数的执行顺序

    函数的嵌套调用

     1 def max2(x,y):
     2     m  = x if x>y else y
     3     return m
     4 
     5 def max4(a,b,c,d):
     6     res1 = max2(a,b)
     7     res2 = max2(res1,c)
     8     res3 = max2(res2,d)
     9     return res3
    10 
    11 # max4(23,-7,31,11)
    12 
    13 函数的嵌套调用
    14 
    15 函数的嵌套调用

    函数的嵌套定义

     1 def f1():
     2     print("in f1")
     3     def f2():
     4         print("in f2")
     5 
     6     f2()
     7 f1()
     8 ###########
     9 def f1():
    10     def f2():
    11         def f3():
    12             print("in f3")
    13         print("in f2")
    14         f3()
    15     print("in f1")
    16     f2()
    17     
    18 f1()
    19 
    20 函数的嵌套定义

    函数的作用域链:小范围作用域可以使用大范围的变量,但是反之不行,他是单向的。

    def f1():
        a = 1
        def f2():
            def f3():
                print(a)
            f3()
        f2()
    
    f1()
    ################
    def f1():
        a = 1
        def f2():
            a = 2
        f2()
        print('a in f1 : ',a)
    
    f1()
    
    作用域链应用举例
  • 相关阅读:
    Ubuntu挂起后无法唤醒的问题以及解决方式
    两个比较给力的开源框架(1.头像选择,拍照,裁剪 2.自定义对话框)
    把APP演示做成GIF图
    单点触控与多点触控
    自定义imageView圆形图片
    自定义imageView圆形
    xmlBean类
    解析xml并展示数据(fragment)
    解析xml并展示数据(mainActivity)
    XStream解析xml代码
  • 原文地址:https://www.cnblogs.com/129TL/p/9450613.html
Copyright © 2011-2022 走看看