Python学习笔记之【不定长参数 *args,**kwargs】2019-08-08

第一节 总览
Section I Overview

  It is well known that if a function defines a formal parameter, then the parameter must be passed when calling the function, otherwise the system will report an error.

  众所周知,如果函数定义了形参,那么调用函数的时候就要传递参数,否则系统将会报错。

#正确的传递参数方式 The right way of passing parameters
In [34]: def ad(a,b):
    ...:     print(a+b)
    ...:     
In [35]: ad(1,2)
3

#错误的传递参数方式  The wrong way to pass parameters
In [34]: def ad(a,b):
    ...:     print(a+b)
In [36]: ad(1)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-36-e6dd8e29e4b8> in <module>()
----> 1 ad(1)

TypeError: ad() missing 1 required positional argument: 'b'

  再看如下两个范例:
   Look at the following two examples:

  我们在函数的参数中加入一个形为*args的参数:
  We add a parameter in the form of * argsto the parameter of the function:

In [23]: def test(a,b,*args):
    ...:     print(a)
    ...:     print(b)
    ...:     print(args)
In [24]: test(1,2)
1
2
()
In [25]: def test(a,b,*args):
    ...:     print(a)
    ...:     print(b)
    ...:     print(args)
In [26]: test(1,2,3,4,5,6)
1
2
(3, 4, 5, 6)

  It can be seen that all the additional parameter functions are received and output in tuple mode. Since it is tuple, can we change the output mode?
  可见多出来的参数函数以元组方式全部接收并进行了输出,既然是元组,那我们是不是可以改变一下输出方式呢?

In [37]: def test(a,b,*args):
    ...:     print(a)
    ...:     print(b)
    ...:     for t in args:
    ...:         print(t)
    ...:         
In [38]: test(1,2,3,4,5,6)
1
2
3
4
5
6

  下面我们再增加一个形参,名为**kwargs
  Let's add another parameter called ** kwargs

In [39]: def test(a,b,*args,**kwargs):
    ...:     print(a)
    ...:     print(b)
    ...:     print(args)
    ...:     print(kwargs)
    ...:     
In [41]: test(1,2)
1
2
()
{}

  在只传递了2个参数的情况下,可以看到第四个参数数据的类型是一个字典。
  With only two parameters passed, you can see that the type of the fourth parameter data is a dict.

  我们用刚才的方式来调用试试看:
  Let's try calling it the way we did just now:

In [42]: test(1,2,3,4,5,6)
1
2
(3, 4, 5, 6)
{}

  这时候我们必须要知道的就是如何才能把参数转入字典中呢?
  Now what we have to know is how to put the parameters into the dict?

  看如下代码:
  Look at the code below:

In [48]: test(1,2,3,4,5,6,7,a23=10,b8="1")
1
2
(3, 4, 5, 6, 7)
{'a23': 10, 'b8': '1'}

  现在可以得知,要传递参数到字典中,参数必须满足XX=XX的模式:
  Now you can see that in order to pass parameters to the dict, the parameters must satisfy the mode XX = XX.

第二节 *args 的解包
Section 2 * Args unpacking

  上节说到,只要在调用函数的时候,不传递带key的参数,那所有的参数都将存入到*args中以元组方式返回。
  As mentioned in the previous section, as long as the parameters with key are not passed when the function is called, all the parameters will be stored in *args and returned as tuples.

  那我们在上面函数定义的代码中稍作改动,让函数在输出 *args 的同时,把 *args 中元素的个数打印出来。
  So let's make a slight change in the code defined by the function above so that the function prints out the number of elements in * args at the same time as it outputs * args.

In [81]: def test(a,b,*args,**kwargs):
    ...:     print(a)
    ...:     print(b)
    ...:     print(args,end='')
    ...:     print("-----*args中元素的个数为:"+str(len(args)))
    ...:     print(kwargs)
    ...:     

In [82]: test(1,2,3,4,5,6,7,8,9)
1
2
(3, 4, 5, 6, 7, 8, 9)-----*args中元素的个数为:7
{}

  我们把函数调用的代码作一丢丢的改动,再来看输出的情况:
  Let's make a little change to the code of the function call, and then look at the output.

In [83]: test(1,2,(3,4,5,6,7,8,9))
1
2
((3, 4, 5, 6, 7, 8, 9),)-----*args中元素的个数为:1
{}

  注意到哪里不同了吗?对,仅仅是加了一对括号()而已。
  Notice what's different? Yes, just a pair of parentheses().

  很好,到这里我们看到了两次“相互对应”的操作,我们调用时传递了7个参数,返回就是7个参数。我们调用时传递了1个参数,返回的也是一个参数。
  Well, here we see two "corresponding" operations. We pass seven parameters when we call, seven parameters when we return, one parameter when we call, and one parameter when we return.

  但是不要忘了,我们是人类,人类是很懒惰的,所以我们想要做的事情就是:我传递刚才的1个参数给你,但是你要分开来返回给我,因为你是计算机,你要多做一点事情。
  But don't forget, we are human beings who are very lazy, so what we want to do is: I pass you a parameter just now, but you have to separate and back it to me, because you are a computer, you have to do more jobs.

  什么都不说,就是干!
  we will say we will do!

In [84]: test(1,2,*(3,4,5,6,7,8,9))
1
2
(3, 4, 5, 6, 7, 8, 9)-----*args中元素的个数为:7
{}

In [85]: 

  哈哈哈,这是不是非常懒,只加了一个*而已!整存零取!
  How lazy we are!Only one *was added.Integral storage and zero fetch.

   这就是解包的含义!

   That's what unpacking means!




  那么我们依葫芦画瓢,再简单看一下dict的解包是什么样子。首先还是要简单修改一下代码,输出一下dict的元素的个数。
  That's what unpacking means! So let's draw a gourd and see what dict's unpacking looks like. First, we need to simply modify the code and output the number of dictelements.

In [85]: def test(a,b,*args,**kwargs):
    ...:     print(a)
    ...:     print(b)
    ...:     print(args,end='')
    ...:     print("-----*args中元素的个数为:"+str(len(args)))
    ...:     print(kwargs,end='')
    ...:     print("-----**kwargs中元素的个数为:"+str(len(kwargs)))
    ...:     

In [86]: test(1,2,3,4,5,6,7,8,9,a1=1,a2=2,a3=3)
1
2
(3, 4, 5, 6, 7, 8, 9)-----*args中元素的个数为:7
{'a1': 1, 'a2': 2, 'a3': 3}-----**kwargs中元素的个数为:3

  现在我们把三个键值对打包看一下,对,应该很简单,就是像刚才那么操作,把后面三对参数用{}括起来,走起!
  Now let's take a look at the three key pairs packaged together. Yes, it should be very simple. Just like what we did just now, we can wrap up the last three pairs of parameters with {},let's go!

In [87]: test(1,2,3,4,5,6,7,8,9,{a1=1,a2=2,a3=3})
  File "<ipython-input-87-879379c68e42>", line 1
    test(1,2,3,4,5,6,7,8,9,{a1=1,a2=2,a3=3})
                              ^
SyntaxError: invalid syntax

  注意看提示,错误的语法....。仔细一看,对哦,字典内元素的格式应该是XX:XX才对!立刻改之!
  Pay attention to the hints, invalid syntax... Look carefully, yeah, the format of the elements in the dict should be XX:XX. Change it immediately!

In [88]: test(1,2,3,4,5,6,7,8,9,{a1:1,a2:2,a3:3})
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-88-3cd0045c1bff> in <module>()
----> 1 test(1,2,3,4,5,6,7,8,9,{a1:1,a2:2,a3:3})

NameError: name 'a1' is not defined

  神马情况?怎么又出错了?再看提示,a1没有定义!
  What's wrong? Look at the hint , a1 is not defined!

  现在我们仔细看上上图正确运行的输出,发现神马没有?
  Now let's take a closer look at the previous output that worked correctly, and find out what?

  对的!上上图的a1、a2、a3已经被解读为了字符串' ',而刚才的代码a1被识别为了变量,而且变量没有定义,自然就报错了。那么我们继续来更正这个错误好了,把a1、a2、a3全部改为字符串类型。
  Right! The a1、a2、a3of the above figure have been interpreted as strings ' ',while the code a1 just now is interpreted as a variable, and the variable is undefined, so the error will occur. So let's go ahead and correct this mistake. Changea1、a2、a3 all to string.

In [89]: test(1,2,3,4,5,6,7,8,9,{'a1':1,'a2':2,'a3':3})
1
2
(3, 4, 5, 6, 7, 8, 9, {'a1': 1, 'a2': 2, 'a3': 3})-----*args中元素的个数为:8
{}-----**kwargs中元素的个数为:0

  这次结果好像没有报错唉!打包应该是已经成功了。咦,但是好像还是有一点超出预期。
  There seems to be no mistake in this result. Packing should have been successful. Gee, but it still seems a little out of expectations.

  我们回忆一下刚才元组的情况,我用()把几个参数括了起来,这个参数包就被*args接收了,那我把键值对用{}括起来了,应该是被**kwargs接收才对啊!
  Let's recall the tuple case just now. I encapsulated several parameters with () and the parameter package was received by *args. Then I encapsulated the key-value pairs with {}, which should be received by **kwargs.

  是不是感觉好有道理,又没有什么证据的感觉^_^!
  Does it make sense to feel good ?

  **kwargs是什么类型?是dict,那就是键和值要成对的出现才行。
  What is the type of **kwargs? It's dict. That's where keys and values appear in pairs.

  我们把字典中的键key和值value比作一双手套的左右两只,然后再考虑这么一个例子:
  We compare the keys keyand value in the dictionary to the left and right of a pair of gloves, and then consider such an example:


  • 你是我的好朋友。
  • You are my best friend.
  • 有一天你被蜘蛛咬了,长出了六只手,结果到了冬天太冷了,你却不敢出门买手套,于是打发我去帮你买。
  • One day you were bitten by a spider and grew six hands. As a result, it was too cold in winter and you dared not go out to buy gloves. So you sent me to buy Gloves for you
  • 人生苦短,我用python。额不,我要和你开个玩笑。于是我把买来的三双手套,锁在了一个铁盒子里,交给了你。
  • Life is short. I use python. No, I'm kidding you. So I locked the three pairs of gloves I bought in an iron box and gave them to you.
  • 亲爱的蜘蛛侠你,瞬间满怒气,开启狂暴怒吼:“贱人!我要的是手套!”
  • Dear Spider-Man you, instantly full of anger, open the rage roar: "Bitch! I want gloves!"
  • 我:“亲爱的,这是手套lol 在盒子里呢lol”
  • Me: "Honey, this is glove in the box."
  • 你:“TMD 驼你是他可已经西去了,我马上就会火,打开快点的,以后跟哥混,妹子少不了”
  • Iron Man is dead, I will be famous soon.Open it now! If you work for me in the future, I will make you rich, rich and enjoyable. Wives and concubines will flock together.
    -我: 好嘞,客官您里屋请,立马开!(此处省略......BYTE)。咋样,合适不?
  • Okay, wait a moment. How's it going? Are you satisfied?
  • 你:好使!
  • Fucking good!

okok,我知道太长了又啰嗦,看不懂是吧,好的我们接下来翻译一下:


  • **kwargs是我的好朋友。
  • 有一天你被蜘蛛咬了,长出了六只手key:value,key:value,key:value,结果到了冬天太冷了,你却不敢出门买手套a1':1,'a2':2,'a3':3,于是打发我去帮你买。
  • 人生苦短,我用python。额不,我要和你开个玩笑。于是我把买来的三双手套a1':1,'a2':2,'a3':3,锁在了一个铁盒子里{a1':1,'a2':2,'a3':3},交给了你。
  • 亲爱的蜘蛛侠你,瞬间满怒气,开启狂暴怒吼:“贱人!我要的是手套a1':1,'a2':2,'a3':3!”
  • 我:“亲爱的,这是手套a1':1,'a2':2,'a3':3lol 在盒子里呢{a1':1,'a2':2,'a3':3}lol”
  • 你:“TMD 驼你是他可已经西去了,我马上就会火,打开快点的,以后跟哥混,妹子少不了”
  • 我: 好嘞,客官您里屋请,立马开**{a1':1,'a2':2,'a3':3}!(此处省略......BYTE)。咋样,合适不?
  • 你:好使!a1':1,'a2':2,'a3':3


In [85]: def test(a,b,*args,**kwargs):
    ...:     print(a)
    ...:     print(b)
    ...:     print(args,end='')
    ...:     print("-----*args中元素的个数为:"+str(len(args)))
    ...:     print(kwargs,end='')
    ...:     print("-----*kwargs中元素的个数为:"+str(len(kwargs)))
In [90]: test(1,2,3,4,5,6,7,8,9,**{'a1':1,'a2':2,'a3':3})
1
2
(3, 4, 5, 6, 7, 8, 9)-----*args中元素的个数为:7
{'a1': 1, 'a2': 2, 'a3': 3}-----*kwargs中元素的个数为:3

大招就是:**{ }

肚子饿,吃饭去了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351