参数函数Python凡人笔记 参数函数

发一下牢骚和主题无关:

    在上一篇笔随《Python常人条记 -- 装饰器》中有园友提出我对Python中的参数法魔表述得不是很确明,故借此机会总结一下,再结合几个例子,望希对大家有帮助。另外竹风应用的是 Python 2.6.6

    参考资料:《Python基础教程》(第2版)Magnus Lie Hetland

    一、Python的函数返回些什么?
    一般说的函数,总会在盘算后之返回点什么。像在 Pascal 里头,就有分函数和进程。让我们一同从例子里头看看 Python 的函数到底会返回些什么。

1 def test():
2     print "This is printed"
3     return
4     print "This is not"

    这里的return句语只起到结束函数的作用:

1 >>> x = test()
2 This is printed
3 
4 >>> x
5 >>>
6 
7 >>> print x
8 None

    可以看到,第二个print句语被跳过了。单单看 x 似乎没有任何东西,通过 “print x” 我们可以看到一个悉熟的值:None。
    这么看来,在Python里头,全部的函数会都返回值;当不要需它们返回值的时候,它们就返回None。

    二、什么类型的参数可以修改?
    函数通过参数来得获一系列的值。在Python中,字符串(以及数字和元组)是不可变的,即没法被修改(也就是说只能用新的值盖覆),用学术点的话来讲:在函数内为不可变类型的参数予赋新值不会变改外部任何变量的值。   

1 >>> def try_to_change(n):
2 ...     n = "Mr Gumby"
3 ...
4 >>> name = "Mrs Entity"
5 >>> try_to_change(name)
6 >>> name
7 'Mrs Entity'

    我们可以看到,name 虽然作为参数递传到函数中,但是最后 name 的值并没有任何变改。其实面上的码代工作方法类似于面下这样:

1 >>>name = "Mrs Entity"
2 >>>n = name    #相称于传参数
3 >>>n = "Mr Gumby"    #在函数外部给n一个新的字符串
4 >>>name
5 'Mrs Entity'

    那么如果我们传的参数是一个可变的数据结构呢,比如列表?估计大家已能猜到结果了。

1 >>> def change(n):
2 ...     n[0] = "Mr Gumby"
3 ...
4 >>> name = ["Mrs Entity", "Mrs Thing"]
5 >>> change(name)
6 >>> name
7 ['Mr Gumby', 'Mrs Thing']

    这里发明参数的值变改了,这也是与眼前的例子中最要重的区分。要弄清楚的是,当两个变量同时引用一个列表的时候,它们的确是同时引用了一个列表。如果想防止涌现种这况情,可以复制一个列表的副本。具体做法就是递传参数的时候,将列表的片分作为参数,比如:change(name[:])。这样的话,原始的列表就是安全的。
    PS:竹风刚入门的时候曾犯过将原始列表传入函数的误错,关键是函数里头有一个 remove 作操,结果大家也能猜到了。。。

    那如果要对一个不可变的参数行进作操呢?比如一个数字,这又该怎么办?
    这个时候我们该应从函数中返回全部要需的值,如果值多于一个拿就用元组的式形返回。例如,将变量的数值增长1的函数可以这么写:

1 >>> def inc(x):return x + 1
2 ...
3 >>> foo = 10
4 >>> foo = inc(foo)
5 >>> foo
6 11

    如果真的想变改参数的话,我们可以应用一点小技能,将值放在列表中(还记得列表是可修改的么?):

1 >>> def inc(x): x[0] = x[0] + 1
2 ...
3 >>> foo = [10]
4 >>> inc(foo)
5 >>> foo
6 [11]

    应用种哪方法,全凭个人好喜~~

    三、置位参数,关键字参数,默许参数
    到目前为止,眼前例子中应用的都是置位参数,因为它们的置位很要重——事实上比它们的名字更要重。先看些单简的列子,来看看为什么会引入关键字参数。

 1 >>> def hello_1(greeting, name):
 2 ...     print "%s, %s!" % (greeting, name)
 3 ...
 4 >>> def hello_2(name, greeting):
 5 ...     print "%s, %s!" % (name, greeting)
 6 ...
 7 >>> hello_1("Hello", "World")
 8 Hello, World!
 9 >>> hello_2("World", "Hello")
10 World, Hello!

    这两个函数所实现的功能是完整一样的,独一的区分就是参数的序顺。当参数很多的时候,竹风得觉参数的序顺是很难住记的。为了让事件单简些,我们可以供给参数的名字。

1 >>> hello_1(greeting = "Hello", name = "World")
2 Hello, World!
3 >>> hello_1(name = "World", greeting = "Hello")
4 Hello, World!
5 >>> hello_2(greeting = "Hello", name = "World")
6 World, Hello!

    供给了参数的名字后,序顺就可有可无的,就似乎面上的 hello_1 用调。独一要意注的,就是参数名和值一定要对应,不然就会涌现 hello_2 那样输出 “World Hello!”了。
    这类应用参数名供给的参数叫做关键字参数。重要作用在于可以确明个每参数的作用,也就防止了面下这样怪奇的用调:

1 >>>stroe("Mr Brainsample", 10, 20, 13, 5)
2 
3 >>>stroe(patient="Mr Brainsample", hour=10, minute=20, day=13, month=5)

    竹风认为,大部分园友瞥见第一种用调的时候估计是虎躯一震的。。。第二种用调虽然打的字多了点,但是参数的含意变得更加清晰,而且就算弄乱了参数的序顺,对于序程的功能也没有任何影响。
    关键字参数最用实的地方在于可以在函数中给参数供给默许值,嘎嘎,再也不必担忧用调函数的时候漏参数了~~   

>>> def hello_3(greeting="Hello", name="World"):
...     print "%s, %s!" % (greeting, name)
...
>>> hello_3()    #应用默许参数
Hello, World!
>>> hello_3('Greetings')    #应用置位参数将值传给greeting
Greetings, World!
>>> hello_3('Greetings','God')    #同时应用置位参数
Greetings, God!
>>> hello_3('Greetings',name = 'Tom')    #置位参数和关键字参数混用
Greetings, Tom!
>>> hello_3(name = 'Jerry')    #只应用关键字参数指定name
Hello, Jerry!

    最后关于置位参数和关键字参数要需意注的是:同时应用置位和关键字参数的时候,必须把置位参数放置在关键字参数的眼前,否则,解释器就不晓得这些参数到底该应处在什么置位了。

    四、集收参数与解开参数
    铺垫了这么久,于终到来天今的两大Boss眼前了。置位参数拉好痛恨,关键字参数做好疗治,其他人全力输出吧!(博主wow五人本打多了。。。视无就好。。。)
    先说说集收参数,在定义函数时,*params 集收其余的置位参数(parameter),返回元组;**kwparams 集收其余的关键字参数(key word parameter),返回字典。
    有时候能供给恣意量数的参数是相称便方的,比如一个函数 add 可以求恣意个数字的和,add(1,2,3) 和 add(1,2,3,4,5) 都能给出确正结果。
    户用可以给函数供给恣意多的参数,实现起来也不难。意注例子中虽然只供给了一个参数,但是眼前加上了个星号。   

1 >>> def print_params(*params):
2 ...     print params
3 ...
4 >>> print_params('Testing')
5 ('Testing',)
6 >>> print_params('Testing',1,2,3)
7 ('Testing', 1, 2, 3)

    可以看到,结果作为元组印打出来。参数前的星号将全部传进来的参数放置在同一个元组中。也可以说是把这些值集收起来,然后应用。当然也可以结合一般参数来应用:

 1 >>> def print_params_2(title, *params):
 2 ...     print "title =",title
 3 ...     print params
 4 ...
 5 >>> print_params_2("Test2", 1, 2, 3)
 6 title = Test2
 7 (1, 2, 3)
 8 >>> print_params_2("Test3")
 9 title = Test3
10 ()

    完整没问题!所以星号的意思就是“集收其余的置位参数”。如果不供给任何集收的元素,params就是个空元组。
    让我们看下关键字参数的“集收”作操。

1 >>> def print_params_3(**kwparams):
2 ...     print kwparams
3 ...
4 >>> print_params_3(x=1, y=2, z=3)
5 {'y': 2, 'x': 1, 'z': 3}

    返回的是字典而不是元组。将它们放在一同看看:

>>> def print_params_4(x, y, z=3, *pospar, **keypar):
...     print x, y, z
...     print pospar
...     print keypar
...
>>> print_params_4(1, 2, 3, 5, 6, 7, foo='A', bar='B')
1 2 3
(5, 6, 7)
{'foo': 'A', 'bar': 'B'}
>>> print_params_4(1, 2, 3)
1 2 3
()
{}

    ok,跟我们期望的结果没有别差。

    集收参数打完了,再来打开展参数。
    开展参数,在用调函数时,*params 将元组拆分为置位参数(parameter)传入;**kwparams 将字典拆分为关键字参数(key word parameter)传入。
    这是两个型典的例子:   

 1 >>> def add(x,y): return x + y
 2 ...
 3 >>> params = (1, 2)
 4 >>> add(*params)
 5 3
 6 >>> def hello_3(greeting="Hello", name="World"):
 7 ...     print "%s, %s!" % (greeting, name)
 8 ...
 9 >>> kwparams = {'name': 'Sir Robin', 'greeting': 'Well met'}
10 >>> hello_3(**kwparams)
11 Well met, Sir Robin!

     最后我们看看这几种方法一同应用的况情:

 1 >>> def finally_test(x, y, z=3, *params, **kwparams):    #参数的序顺该应为:置位参数,关键字参数,*params,**kwparams
 2 ...     print "pos x =",x
 3 ...     print "pos y =",y
 4 ...     print "key z =",z
 5 ...     print "params =",params
 6 ...     print "kwparams =",kwparams
 7 ...
 8 >>> list = [1,2,3,4,5]
 9 >>> dict = {"foo":"A", "bar":"B"}
10 
11 >>> finally_test(1,2,*list,**dict)    #没有指定z的值,所以将list[0]作为z的值,其他集收为params
12 pos x = 1
13 pos y = 2
14 key z = 1
15 params = (2, 3, 4, 5)
16 kwparams = {'foo': 'A', 'bar': 'B'}
17 
18 >>> finally_test(1,2,3,list,dict)    #误错的用调方法,会将dict也认为是个置位参数
19 pos x = 1
20 pos y = 2
21 key z = 3
22 params = ([1, 2, 3, 4, 5], {'foo': 'A', 'bar': 'B'})
23 kwparams = {}
24 
25 >>> finally_test(1,2)    #没有余多的置位参数和关键字参数的况情
26 pos x = 1
27 pos y = 2
28 key z = 3
29 params = ()
30 kwparams = {}
31 
32 >>> finally_test(1,2,3,*list,**dict)    #确正的用调方法
33 pos x = 1
34 pos y = 2
35 key z = 3
36 params = (1, 2, 3, 4, 5)
37 kwparams = {'foo': 'A', 'bar': 'B'}

    其实一般况情下会这么定义函数:
    def foo(*params,**kwparams):
        pass

    到这里就总结完了,望希对大家用有。若有足不,迎欢大家正指交流,感谢^_^

文章结束给大家分享下程序员的一些笑话语录: 马云喜欢把自己包装成教主,张朝阳喜欢把自己包装成明星,李彦宏喜欢把自己包装成的很知性,丁磊喜欢把自己包装的有创意,李开复总摆出一副叫兽的样子。看来的。其实我想说,缺啥补啥,人之常情。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值