*args**kwargs 傻傻分不清楚

上次发布后,后台有粉丝留言,说不太明白这个args 和*kwargs 的用法。其实这个问题经常在面试中被问到,以前是靠死记硬背,还经常记混,记得老师教过,这是可变参数,*args 是把参数变成元组,**kwargs 是转成字典。真是这样吗?还是实践一下吧:

''' *args又叫可变参数,
    会把参数解析成tuple,
    **kwargs又叫关键字参数,
    会把key=value这样的键值对
    参数解析成dict,至于叫什么随意,
    args和kwargs只是约定俗成,前面有
    *和**就行,比如我就叫*anything'''

def func(a,b=1,*anything):
    print(a)
    print(b)
    print("args:",anything)

def funca(**kwargs):
    print("kwargs:",kwargs)

def funcb(*anything,**anything):
    print("args=",args)
    print("anything=",anything)

if __name__ == "__main__":
   func(0,1,'无敌哥流批',[22,33],44)
   print("---我是分割线---")
   funca(a=1,b=2,c=3)
   print("---我是分割线---")
   funcb([0,1,"t"],1,None,a=1,b=2,c=3)

运行结果
0
1
args: ('无敌哥流批', [22, 33], 44)
---我是分割线---
kwargs: {'a': 1, 'b': 2, 'c': 3}
---我是分割线---
args= ([0, 1, 'test'], 1, None)
anything= {'a': 1, 'b': 2, 'c': 3}

结果和预想的一样,但是他们其实是有顺序的,固定参数>默认参数>可变参数>关键字参数,搞乱顺序,结果就是

SyntaxError: positional argument 
follows keyword argument

回到正题 上节课的作业


老实说,无敌哥这个作业给我看懵了,没明白他的意思,什么是@loop@loop(5) 又是怎么来的,这俩还是同一个装饰器么?直到看了他的解答才恍然大悟:

def run(times):
'''这个callable方法是核心'''
    if callable(times):
        def wrapper(*args, **kwargs):
            for i in range(5):
                times(*args, **kwargs)
                print(f"运行的第{i}次")

        return wrapper
    else:
        def decorator(func):
            def wrapper(*args, **kwargs):
                for i in range(times):
                    func(*args, **kwargs)
                    print(f"运行的第{i}次")

            return wrapper

        return decorator

'''没有加参数,callable是True,会运行5次'''
@run 
def func():
    print("func运行了")
'''此时callable是False,则会按照传参运行相应次数'''    
@run(1)
def func1():
    print("func1运行了")
if __name__=="__main__":
    func()
    print("---我是分割线---")
    func1()     

原来是利用了 callable 这个方法,来判断函数是否是可以调用的,相当于变相搞了一个 if else 的判断,如果是 True 的就走 A 路线,否则就是 B 路线,真是,妙啊。

时候不早了,先卷到这。接下来都是硬茬,有的啃了。诸位,咱们青山不改,绿水长流,下期见。


↙↙↙阅读原文可查看相关链接,并与作者交流