python函数的参数类型和传递值类型可以不同吗_Python函数参数类型*、**的区别

a,b,c,d,e = x

print a,b,c,d,e

#特别说明:x也可以为dict类型,x为dick类型时将键传递给函数

>>> y

{'a': 1, 'c': 6, 'b': 2, 'e': 1, 'd': 1}

>>> test(*y)

a c b e d

#---------------------------------

#**dict_grp_kw_args方式

>>> y

{'a': 1, 'c': 6, 'b': 2, 'e': 1, 'd': 1}

>>> test(**y)

1 2 6 1 1

#这种函数处理方式等价于

a = y['a']

b = y['b']

... #c,d,e不再赘述

print a,b,c,d,e

2. 不同类型参数混用需要注意的一些细节  接下来说明不同参数类型混用的情况,要理解不同参数混用得语法需要理解以下几方面内容.

首先要明白,函数调用使用参数类型必须严格按照顺序,不能随意调换顺序,否则会报错. 如 (a=1,2,3,4,5)会引发错误,; (*x,2,3)也会被当成非法.

其次,函数对不同方式处理的顺序也是按照上述的类型顺序.因为#keyword_args方式和**dict_grp_kw_args方式对参数一一指定,所以无所谓顺序.所以只需要考虑顺序赋值(positional_args)和列表赋值(*tuple_grp_nonkw_args)的顺序.因此,可以简单理解为只有#positional_args方式,#*tuple_grp_nonkw_args方式有逻辑先后顺序的.

最后,参数是不允许多次赋值的.

举个例子说明,顺序赋值(positional_args)和列表赋值(*tuple_grp_nonkw_args)的逻辑先后关系:

代码如下:

#只有在顺序赋值,列表赋值在结果上存在罗辑先后关系

#正确的例子1

>>> x = {3,4,5}

>>> test(1,2,*x)

1 2 3 4 5

#正确的例子2

>>> test(1,e=2,*x)

1 3 4 5 2

#错误的例子

>>> test(1,b=2,*x)

Traceback (most recent call last):

File "", line 1, in TypeError: test() got multiple values for keyword argument 'b'

#正确的例子1,处理等价于

a,b = 1,2 #顺序参数

c,d,e = x #列表参数

print a,b,c,d,e

#正确的例子2,处理等价于

a = 1 #顺序参数

e = 2 #关键字参数

b,c,d = x #列表参数

#错误的例子,处理等价于

a = 1 #顺序参数

b = 2 #关键字参数

b,c,d = x #列表参数

#这里由于b多次赋值导致异常,可见只有顺序参数和列表参数存在罗辑先后关系

函数声明区别

理解了函数调用中不同类型参数得区别之后,再来理解函数声明中不同参数得区别就简单很多了.

1. 函数声明中的参数类型说明

函数声明只有3种类型, arg, *arg , **arg 他们得作用和函数调用刚好相反. 调用时*tuple_grp_nonkw_args将列表转换为顺序参数,而声明中的*arg的作用是将顺序赋值(positional_args)转换为列表. 调用时**dict_grp_kw_args将字典转换为关键字参数,而声明中**arg则反过来将关键字参数(keyword_args)转换为字典.

特别提醒:*arg 和 **arg可以为空值.

以下举例说明上述规则:

代码如下:

#arg, *arg和**arg作用举例

def test2(a,*b,**c):

print a,b,c

#---------------------------

#*arg 和 **arg可以不传递参数

>>> test2(1)

1 () {}

#arg必须传递参数

>>> test2()

Traceback (most recent call last):

File "", line 1, in TypeError: test2() takes at least 1 argument (0 given)

#----------------------------

#*arg将顺positional_args转换为列表

>>> test2(1,2,[1,2],{'a':1,'b':2})

1 (2, [1, 2], {'a': 1, 'b': 2}) {}

#该处理等价于

a = 1 #arg参数处理

b = 2,[1,2],{'a':1,'b':2} #*arg参数处理

c = dict() #**arg参数处理

print a,b,c

#-----------------------------

#**arg将keyword_args转换为字典

>>> test2(1,2,3,d={1:2,3:4}, c=12, b=1)

1 (2, 3) {'c': 12, 'b': 1, 'd': {1: 2, 3: 4}}

#该处理等价于

a = 1 #arg参数处理

b= 2,3 #*arg参数处理

#**arg参数处理

c = dict()

c['d'] = {1:2, 3:4}

c['c'] = 12

c['b'] = 1

print a,b,c

2. 处理顺序问题

函数总是先处理arg类型参数,再处理*arg和**arg类型的参数. 因为*arg和**arg针对的调用参数类型不同,所以不需要考虑他们得顺序.

代码如下:

def test2(a,*b,**c):

print a,b,c

>>> test2(1, b=[1,2,3], c={1:2, 3:4},a=1)

Traceback (most recent call last):

File "", line 1, in TypeError: test2() got multiple values for keyword argument 'a'

#这里会报错得原因是,总是先处理arg类型得参数

#该函数调用等价于

#处理arg类型参数:

a = 1

a = 1 #多次赋值,导致异常

#处理其他类型参数

...

print a,b,c

闭包  python的函数,原本只能访问两个区域的变量:全局,和局部(函数上下文). 实际上,函数本身也是一个对象,也有自己的作用域. 闭包通过函数与引用集合的组合,使得函数可以在它被定义的区域之外执行. 这个集合可以通过func_closure来获取这个引用集合. 这与python处理全局变量得方式一样,只不过全局变量将引用集合存储在__globals__字段中.func_closure是一个存储cell类型的元组,每个cell存储一个上下文变量.

另外,旧版本得python的内部函数不能在其他作用域使用的原因,并不是因为每个作用域的变量严格相互隔离,而是脱离原本的作用域后,函数失去了原本上下文的引用。需要注意的是,闭包存储的上下文信息一样是浅拷贝,所以传递给内部函数的可变对象仍然会被其他拥有该对象引用得变量修改.

举个例子:

本站所有资源全部来源于网络,若本站发布的内容侵害到您的隐私或者利益,请联系我们删除!

合作方式

Copyright © 2004-2018 https://www.gxlcms.com/. All Rights Reserved.

豫ICP备19030742号

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值