函数的进阶

 

 

函数的进阶

函数参数--动态传参

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

1.动态接受位置参数

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

现在问题来了. 我想吃任意的食物. 数量是任意的, 食物也是任意的. 这时我们就要就到
动态参数了.
在参数位置编写*表示接收任意内容

def chi(*food): # * 表示的是不定参数. 可以传递任意个信息 参数名是food, 接受到的是元组
    print("我要吃", food)

chi("一锅大米饭", "一箱辣条", "一桶方便面", "4L可乐")
chi("方便面")
chi("一大锅米饭", "一小锅小米饭", "一箱辣条", "一桶方便面", "4L可乐")

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

这时程序运行会报错. 因为前⾯传递进去的所有位置参数都被*food接收了. ab接收
不到参数

所以必须改写成以下代码:

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

 

如果默认值参数在*args前面. 如果想让默认值生效. *args将永远接不到值
def func( a, b, *args,c = 5): # arguments参数
    print(a, b, c, args)

func(1,2,3,4,5,6,8,c = 10)

 

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

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

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

def func(**kwargs): # key word arguments
    print(kwargs)

func(a=10, b=20, jay="周杰伦", jj="林俊杰")

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

 

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

最终顺序:位置参数 > *args >默认值参数 >**kwargs

这四个参数可以接受任意使用

如果要接受所有的参数:

# 无敌模式. 所有的参数都能接收
def func(*args, **kwargs):
    print(args)
    print(kwargs)
func(1, 2, 5, jj="陶喆", jay="zhoujielun", soup="胡辣汤")

def func(*args): # 在这里. 其实相当于把传进来的参数做了一次聚合, 聚合成一个元组
    print(args)

lst = "娃哈哈"
func(*lst) #  在实参位置 * 表示打散, 打散的是可迭代对象
def func(**kwargs): # ** 把接收到的关键字参数打包(聚合)成字典
    print(kwargs) # 一定是字典

dic = {"张无忌": "明教教主", "谢逊": "金毛狮王", "范瑶": "光明右使"}

func(张无忌=dic['张无忌'], 谢逊=dic['谢逊'], 范瑶=dic['范瑶'])
func(**dic) # 这里的** 是把字典打散. 字典的key作为参数的名字, 字典的值作为参数的值传递给形参
在形参上
1. 位置参数
2. 默认值参数
3. 动态参数
1. *args 位置参数的动态传参. 系统会自动的把所有的位置参数聚合成元组
2. **kwargs 关键字的动态传参. 系统会自动把所有的关键字参数聚合成字典
3. def func(*args, **kwargs): 无敌传参
4. 顺序: 位置参数, *args, 默认值, **kwargs
5. 在使用的时候, 可以任意的进行搭配
4. 在实参上. *, **表示的打散. 在形参. *,** 表示聚合

 

 

命名空间:

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

# 最开始会开辟一个自己的命名空间- 内置名称空间
a = 10
print(a)
# 直接在py文件一个层面上是全局名称空间
def func():
    hasakey = 10
# 在函数内部属于局部名称空间
func()
加载顺序: 内置 => 全局 => 局部
取值顺序: 局部 => 全局 => 内置
a = 10 # 全局
def func():
    a = 20
    print(a)

func()

作用域: 作用域就是作用范围, 按照生效范围来看分为 全局作用域和局部作用域
全局作用域: 包含内置命名空间和全局命名空间. 在整个文件的任何位置都可以使用(遵循
从上到下逐行执行). 局部作用域: 在函数内部可以使用.
作用域命名空间:
1. 全局作用域: 全局命名空间 + 内置命名空间
2. 局部作用域: 局部命名空间
我们可以通过globals()函数来查看全局作⽤域中的内容, 也可以通过locals()来查看局部作用
域中的变量和函数信息

作用域: 变量或者函数的声明周期
全局作用域: 全局名称空间+内置名称空间
局部作用域: 局部名称空间
a = 10 # 全局
def func():
    liuwei = "刘伟"
# 1. globals() 查看全局作用域中的所有内容
qiao = "乔峰"
def 抗收音机():
    bgm = "难念的经"
    print("娃哈哈")
    print(locals())
抗收音机()

# print(globals()) # 查看全局作用域中的内容
# print(locals()) # locals()查看的是当前作用域中的内容

 

函数的嵌套

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

def func1():
    print("我是func1")

def func2():
    print("我是func2")
    func1()

def func3():
    func2()
    print("我是func3")
func3()
这样的代码不是嵌套. 互相调用
函数可以互相嵌套
def outer():
    def inner():
        print("我是内部")
    print("我是外部")
    inner()

outer()

def outer():
    print("我是外面的")
    def inner_1():
        def inner_2():
            print("我是里面的2")
        inner_2()
        print("我是里面的1")
    inner_1()
    print("我是外面的收尾")

outer()

 

关键字 global和nonlocal

  首先我们要写这样的一个代码,首先在全局声明一个变量然后再局部调用这个变量,改变这个变量的值

 

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

print(a) # 10
func() # 20
print(a) # 20

 

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)
nonlocal深坑

# global 引入全局变量, 可以定义全局变量
# nonlocal 引入局部中离他最近的外层变量

def func():
    global a # 没有也得有. 自动帮你创建
    a = 20

func()
print(a)

 

 

 

练习:

# 写函数,接收n个数字,求这些参数数字的和。(动态传参)
def func(*n):
    sum = 0
    for el in n:
        sum += el
    return sum

ret = func(1,2,5,4,7)


# 写函数,传入函数中多个实参(均为可迭代对象如字符串,列表,元祖,集合等),
# 将每个实参的每个元素依次添加到函数的动态参数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,3,5], *(456,789))


# 写函数,传入函数中多个实参(实参均为字典),将每个实参的键值对依次添加到函数的动态参数kwargs里面.
# 例如 传入函数两个参数{‘name’:’alex’} {‘age’:1000}最终kwargs为{‘name’:’alex’ ,‘age’:1000}
def func(**kwargs):
    print(kwargs)

func(**{"alex": "大帅逼", "wusir":""})



# 9,写函数,接收一个参数(此参数类型必须是可迭代对象),将可迭代对象的每个元素以’_’相连接,形成新的字符串,并返回.
# 例如 传入的可迭代对象为[1,'老男孩','武sir']返回的结果为’1_老男孩_武sir’
def func(it):
    result = ""
    for el in it:
        result += str(el) + "_"
    return result[:-1]
    
    for i in range(len(it)):
        el = str(it[i])
        it[i] = el
    return "_".join(it)

print(func([1,"alex","wusiar"]))
print("alex"+213)


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

def func(*n):
    return {"最大值":max(n), "最小值":min(n)}

print(func(1,8,6,4,5,15,63,35,5))


# 求阶乘
def func(n):
    sum = 1
    for i in range(n, 0, -1):
        sum *= i
    return sum
print(func(5))



# 写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组
# 例如:[(‘红心’,2),(‘草花’,2), …(‘黑桃’,‘A’)]

# 花色:红黑芳草
# 点数: A2345678910
# 笛卡儿积.
def func():
    hua = ["红心", "黑桃", "梅花", "方块"]
    dian = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
    result = []
    for huase in hua:
        for dianshu in dian:
            result.append((huase, dianshu))
    return result
#
#
def wrapper():
    def inner():
        print(666)

    return inner # 函数名可以作为变量返回
#
#
fn = wrapper()
fn()

def extendList(val, list=[]): # 默认值在内存中只会产生一份
    list.append(val)
    return list

list1 = extendList(10)
print('list1=%s' % list1)
list2 = extendList(123, [])
print('list2=%s' % list2)
list3 = extendList('a')
print('list3=%s' % list3)

print(id(list1))
print(id(list3))
print(id(list2))
练习

 

 


posted @ 2018-09-18 16:36  赵瑞鑫  阅读(133)  评论(0编辑  收藏  举报