十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
1. 不同类型的参数简述
专注于为中小企业提供成都做网站、网站建设、外贸营销网站建设服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业大厂免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了1000+企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
#这里先说明python函数调用得语法为:
复制代码
代码如下:
func(positional_args,
keyword_args,
*tuple_grp_nonkw_args,
**dict_grp_kw_args)
#为了方便说明,之后用以下函数进行举例
def test(a,b,c,d,e):
print a,b,c,d,e
举个例子来说明这4种调用方式得区别:
复制代码
代码如下:
#
#positional_args方式
test(1,2,3,4,5)
1 2 3 4 5
#这种调用方式的函数处理等价于
a,b,c,d,e = 1,2,3,4,5
print a,b,c,d,e
#
#keyword_args方式
test(a=1,b=3,c=4,d=2,e=1)
1 3 4 2 1
#这种处理方式得函数处理等价于
a=1
b=3
c=4
d=2
e=1
print a,b,c,d,e
#
#*tuple_grp_nonkw_args方式
x = 1,2,3,4,5
test(*x)
1 2 3 4
5
#这种方式函数处理等价于
复制代码
代码如下:
a,b,c,d,e = x
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不再赘述
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 "stdin", line 1, in module
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 "stdin", line 1,
in module
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
a,b,c
2. 处理顺序问题
函数总是先处理arg类型参数,再处理*arg和**arg类型的参数.
因为*arg和**arg针对的调用参数类型不同,所以不需要考虑他们得顺序.
复制代码
代码如下:
def test2(a,*b,**c):
a,b,c
test2(1, b=[1,2,3], c={1:2, 3:4},a=1)
Traceback (most
recent call last):
File "stdin", line 1, in
module
TypeError: test2() got multiple values for keyword argument
'a'
#这里会报错得原因是,总是先处理arg类型得参数
#该函数调用等价于
#处理arg类型参数:
a = 1
a = 1
#多次赋值,导致异常
#处理其他类型参数
...
print a,b,c
def foo(x,y):
... def bar():
x,y
... return bar
...
#查看func_closure的引用信息
a =
[1,2]
b = foo(a,0)
b.func_closure[0].cell_contents
[1, 2]
b.func_closure[1].cell_contents
b()
[1, 2] 0
#可变对象仍然能被修改
a.append(3)
b.func_closure[0].cell_contents
[1, 2, 3]
b()
[1, 2, 3] 0
Python中查看函数参数有四种方式:
1. F(arg1,arg2,…)
这是最常见的定义方式,一个函数可以定义任意个参数,每个参数间用逗号分割,用这种方式定义的函数在调用的的时候也必须在函数名后的小括号里提供个数相等的值(实际参数),而且顺序必须相同,也就是说在这种调用方式中,形参和实参的个数必须一致,而且必须一一对应,也就是说第一个形参对应这第一个实参。例如:
代码如下:
def a(x,y):print x,y
调用该函数,a(1,2)则x取1,y取2,形参与实参相对应,如果a(1)或者a(1,2,3)则会报错。
2. F(arg1,arg2=value2,…)
这种方式就是第一种的改进版,提供了默认值,例如:
代码如下:
def a(x,y=3):print x,y
调用该函数,a(1,2)同样还是x取1,y取2,但是如果a(1),则不会报错了,这个时候x还是1,y则为默认的3。上面这俩种方式,还可以更换参数位置,比如a(y=4,x=3)用这种形式也是可以的。
3. F(*arg1)
上面两种方式是有多少个形参,就传进去多少个实参,但有时候会不确定有多少个参数,则此时第三种方式就比较有用,它以一个*加上形参名的方式来表示这个函数的实参个数不定,可能为0个也可能为n个。注意一点是,不管有多少个,在函数内部都被存放在以形参名为标识符的元组中。
代码如下:
def a(*x):print x
a(1,2,3)
(1, 2, 3)
a(x=1,y=2,z=3)
Traceback (most recent call last):
File "stdin", line 1, in module
TypeError: a() got an unexpected keyword argument 'x'
4. F(**arg1)
形参名前加两个*表示,参数在函数内部将被存放在以形式名为标识符的dictionary中,这时调用函数的方法则需要采用arg1=value1,arg2=value2这样的形式。
代码如下:
def a(**x):print x
a(x=1,y=2,z=3)
{'y': 2, 'x': 1, 'z': 3} #存放在字典中
a(1,2,3) #这种调用则报错
Traceback (most recent call last):
File "stdin", line 1, in module
TypeError: a() takes exactly 0 arguments (3 given)
import math
a = abs
print(a(-1))
n1 = 255
print(str(hex(n1)))
def my_abs(x):
# 增加了参数的检查
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x = 0:
return x
else:
return -x
print(my_abs(-3))
def nop():
pass
if n1 = 255:
pass
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
x, y = move(100, 100, 60, math.pi / 6)
print(x, y)
tup = move(100, 100, 60, math.pi / 6)
print(tup)
print(isinstance(tup, tuple))
def quadratic(a, b, c):
k = b * b - 4 * a * c
# print(k)
# print(math.sqrt(k))
if k 0:
print('This is no result!')
return None
elif k == 0:
x1 = -(b / 2 * a)
x2 = x1
return x1, x2
else:
x1 = (-b + math.sqrt(k)) / (2 * a)
x2 = (-b - math.sqrt(k)) / (2 * a)
return x1, x2
print(quadratic(2, 3, 1))
def power(x, n=2):
s = 1
while n 0:
n = n - 1
s = s * x
return s
print(power(2))
print(power(2, 3))
def enroll(name, gender, age=8, city='BeiJing'):
print('name:', name)
print('gender:', gender)
print('age:', age)
print('city:', city)
enroll('elder', 'F')
enroll('android', 'B', 9)
enroll('pythone', '6', city='AnShan')
def add_end(L=[]):
L.append('end')
return L
print(add_end())
print(add_end())
print(add_end())
def add_end_none(L=None):
if L is None:
L = []
L.append('END')
return L
print(add_end_none())
print(add_end_none())
print(add_end_none())
def calc(*nums):
sum = 0
for n in nums:
sum = sum + n * n
return sum
print(calc(1, 2, 3))
print(calc())
l = [1, 2, 3, 4]
print(calc(*l))
def foo(x, y):
print('x is %s' % x)
print('y is %s' % y)
foo(1, 2)
foo(y=1, x=2)
def person(name, age, **kv):
print('name:', name, 'age:', age, 'other:', kv)
person('Elder', '8')
person('Android', '9', city='BeiJing', Edu='人民大学')
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, **extra)
def person2(name, age, *, city, job):
print(name, age, city, job)
person2('Pthon', 8, city='BeiJing', job='Android Engineer')
def person3(name, age, *other, city='BeiJing', job='Android Engineer'):
print(name, age, other, city, job)
person3('Php', 18, 'test', 1, 2, 3)
person3('Php2', 28, 'test', 1, 2, 3, city='ShangHai', job='Pyhton Engineer')
def test2(a, b, c=0, *args, key=None, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'key=', key, 'kw =', kw)
test2(1, 2, 3, 'a', 'b', 'c', key='key', other='extra')
args = (1, 2, 3, 4)
kw = {'d': 99, 'x': '#'}
test2(*args, **kw)
isinstance(object, class)函数,检查某个对象是不是某个类里的 例如: isinstance(1,int) True 但是这个能不用就不用,毕竟你只要某个对象有某个方法就好,这样破坏的对象“多态”的特征。