重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
import math
成都创新互联-专业网站定制、快速模板网站建设、高性价比建昌网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式建昌网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖建昌地区。费用合理售后完善,10多年实体公司更值得信赖。
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)
刚学用Python的时候,特别是看一些库的源码时,经常会看到func(*args, **kwargs)这样的函数定义,这个*和**让人有点费解。其实只要把函数参数定义搞清楚了,就不难理解了。
先说说函数定义,我们都知道,下面的代码定义了一个函数funcA
def funcA():
pass
显然,函数funcA没有参数(同时啥也不干:D)。
下面这个函数funcB就有两个参数了,
def funcB(a, b):
print a
print b
调用的时候,我们需要使用函数名,加上圆括号扩起来的参数列表,比如 funcB(100, 99),执行结果是:
100
99
很明显,参数的顺序和个数要和函数定义中一致,如果执行funcB(100),Python会报错的:
TypeError: funcB() takes exactly 2 arguments (1 given)
我们可以在函数定义中使用参数默认值,比如
def funcC(a, b=0):
print a
print b
在函数funcC的定义中,参数b有默认值,是一个可选参数,如果我们调用funcC(100),b会自动赋值为0。
OK,目前为止,我们要定义一个函数的时候,必须要预先定义这个函数需要多少个参数(或者说可以接受多少个参数)。一般情况下这是没问题的,但是也有在定义函数的时候,不能知道参数个数的情况(想一想C语言里的printf函数),在Python里,带*的参数就是用来接受可变数量参数的。看一个例子
def funcD(a, b, *c):
print a
print b
print "length of c is: %d " % len(c)
print c
调用funcD(1, 2, 3, 4, 5, 6)结果是
1
2
length of c is: 4
(3, 4, 5, 6)
我们看到,前面两个参数被a、b接受了,剩下的4个参数,全部被c接受了,c在这里是一个tuple。我们在调用funcD的时候,至少要传递2个参数,2个以上的参数,都放到c里了,如果只有两个参数,那么c就是一个empty tuple。
好了,一颗星我们弄清楚了,下面轮到两颗星。
上面的例子里,调用函数的时候,传递的参数都是根据位置来跟函数定义里的参数表匹配的,比如funcB(100, 99)和funcB(99, 100)的执行结果是不一样的。在Python里,还支持一种用关键字参数(keyword argument)调用函数的办法,也就是在调用函数的时候,明确指定参数值付给那个形参。比如还是上面的funcB(a, b),我们通过这两种方式调用
funcB(a=100, b=99)
和
funcB(b=99, a=100)
结果跟funcB(100, 99)都是一样的,因为我们在使用关键字参数调用的时候,指定了把100赋值给a,99赋值给b。也就是说,关键字参数可以让我们在调用函数的时候打乱参数传递的顺序!
另外,在函数调用中,可以混合使用基于位置匹配的参数和关键字参数,前题是先给出固定位置的参数,比如
def funcE(a, b, c):
print a
print b
print c
调用funcE(100, 99, 98)和调用funcE(100, c=98, b=99)的结果是一样的。
好了,经过以上铺垫,两颗星总算可以出场了:
如果一个函数定义中的最后一个形参有 ** (双星号)前缀,所有正常形参之外的其他的关键字参数都将被放置在一个字典中传递给函数,比如:
def funcF(a, **b):
print a
for x in b:
print x + ": " + str(b[x])
调用funcF(100, c='你好', b=200),执行结果
100
c: 你好
b: 200
大家可以看到,b是一个dict对象实例,它接受了关键字参数b和c。
Python函数的参数类型主要包括必选参数、可选参数、可变参数、位置参数和关键字参数,本文介绍一下他们的定义以及可变数据类型参数传递需要注意的地方。
必选参数(Required arguments)是必须输入的参数,比如下面的代码,必须输入2个参数,否则就会报错:
其实上面例子中的参数 num1和num2也属于关键字参数,比如可以通过如下方式调用:
执行结果:
可选参数(Optional arguments)可以不用传入函数,有一个默认值,如果没有传入会使用默认值,不会报错。
位置参数(positional arguments)根据其在函数定义中的位置调用,下面是pow()函数的帮助信息:
x,y,z三个参数的的顺序是固定的,并且不能使用关键字:
输出:
在上面的pow()函数帮助信息中可以看到位置参数后面加了一个反斜杠 / ,这是python内置函数的语法定义,Python开发人员不能在python3.8版本之前的代码中使用此语法。但python3.0到3.7版本可以使用如下方式定义位置参数:
星号前面的参数为位置参数或者关键字参数,星号后面是强制关键字参数,具体介绍见强制关键字参数。
python3.8版本引入了强制位置参数(Positional-Only Parameters),也就是我们可以使用反斜杠 / 语法来定义位置参数了,可以写成如下形式:
来看下面的例子:
python3.8运行:
不能使用关键字参数形式赋值了。
可变参数 (varargs argument) 就是传入的参数个数是可变的,可以是0-n个,使用星号( * )将输入参数自动组装为一个元组(tuple):
执行结果:
关键字参数(keyword argument)允许将任意个含参数名的参数导入到python函数中,使用双星号( ** ),在函数内部自动组装为一个字典。
执行结果:
上面介绍的参数可以混合使用:
结果:
注意:由于传入的参数个数不定,所以当与普通参数一同使用时,必须把带星号的参数放在最后。
强制关键字参数(Keyword-Only Arguments)是python3引入的特性,可参考:。 使用一个星号隔开:
在位置参数一节介绍过星号前面的参数可以是位置参数和关键字参数。星号后面的参数都是强制关键字参数,必须以指定参数名的方式传参,如果强制关键字参数没有设置默认参数,调用函数时必须传参。
执行结果:
也可以在可变参数后面命名关键字参数,这样就不需要星号分隔符了:
执行结果:
在Python对象及内存管理机制中介绍了python中的参数传递属于对象的 引用传递 (pass by object reference),在编写函数的时候需要特别注意。
先来看个例子:
执行结果:
l1 和 l2指向相同的地址,由于列表可变,l1改变时,l2也跟着变了。
接着看下面的例子:
结果:
l1没有变化!为什么不是[1, 2, 3, 4]呢?
l = l + [4]表示创建一个“末尾加入元素 4“的新列表,并让 l 指向这个新的对象,l1没有进行任何操作,因此 l1 的值不变。如果要改变l1的值,需要加一个返回值:
结果:
下面的代码执行结果又是什么呢?
执行结果:
和第一个例子一样,l1 和 l2指向相同的地址,所以会一起改变。这个问题怎么解决呢?
可以使用下面的方式:
也可以使用浅拷贝或者深度拷贝,具体使用方法可参考Python对象及内存管理机制。这个问题在Python编程时需要特别注意。
本文主要介绍了python函数的几种参数类型:必选参数、可选参数、可变参数、位置参数、强制位置参数、关键字参数、强制关键字参数,注意他们不是完全独立的,比如必选参数、可选参数也可以是关键字参数,位置参数可以是必选参数或者可选参数。
另外,python中的参数传递属于对象的 引用传递 ,在对可变数据类型进行参数传递时需要特别注意,如有必要,使用python的拷贝方法。
参考文档:
--THE END--
位置参数适合参数少的情况,当参数较多时,位置容易存错。
关键词参数适合参数较多时,通过指定关键词来存。
混搭时应注意先放位置参数后放关键词参数,否则会出现语法错误。语法上允许混搭,但尽量不要采用。
d在*的前面,可以作为位置参数,不用指定关键词,*后面必须指定关键词,可以混搭。
一旦设置默认值,可以不传它;但也可以继续传入,传了多少就是多少。默认参数需要注意,现房非默认参数再放默认参数。
当参数是多个时,可以在变量前面加*,表示零到无穷多个位置参数,传入的参数会被合并为一个元组,若需要破开元组,只需要在元组前面加上*。注意要先固定参数再可变参数。
在变量前加**,表示可变参数是关键词参数,在调用时必须用键值对来调用。
顺序必须是:必选参数、默认参数、可变位置参数、命名关键字参数和可变关键字参数。
/ 前面一定为位置参数
文章知识点与官方知识档案匹配,可进一步学习相关知识!!!
python 的函数参数类型分为4种:
1.位置参数:调用函数时根据函数定义的参数位置来传递参数,位置参数也可以叫做必要参数,函数调用时必须要传的参数。
当参数满足函数必要参数传参的条件,函数能够正常执行:
add(1,2) #两个参数的顺序必须一一对应,且少一个参数都不可以
当我们运行上面的程序,输出:
当函数需要两个必要参数,但是调用函数只给了一个参数时,程序会抛出异常
add(1)
当我们运行上面的程序,输出:
当函数需要两个必要参数,但是调用函数只给了三个参数时,程序会抛出异常
add(1,2,3)
当我们运行上面的程序,输出
2.关键字参数:用于函数调用,通过“键-值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
add(1,2) # 这种方式传参,必须按顺序传参:x对应1,y对应:2
add(y=2,x=1) #以关健字方式传入参数(可以不按顺序)
正确的调用方式
add(x=1, y=2)
add(y=2, x=1)
add(1, y=2)
以上调用方式都是允许的,能够正常执行
错误的调用方式
add(x=1, 2)
add(y=2, 1)
以上调用都会抛出SyntaxError 异常
上面例子可以看出:有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序的
3.默认参数:用于定义函数,为参数提供默认值,调用函数时可传可不传该默认参数的值,所有位置参数必须出现在默认参数前,包括函数定义和调用,有多个默认参数时,调用的时候,既可以按顺序提供默认参数,也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上
默认参数的函数定义
上面示例第一个是正确的定义位置参数的方式,第二个是错误的,因为位置参数在前,默认参数在后
def add1(x=1,y) 的定义会抛出如下异常
默认参数的函数调用
注意:定义默认参数默认参数最好不要定义为可变对象,容易掉坑
不可变对象:该对象所指向的内存中的值不能被改变,int,string,float,tuple
可变对象,该对象所指向的内存中的值可以被改变,dict,list
这里只要理解一下这个概念就行或者自行百度,后续会写相关的专题文章讲解
举一个简单示例
4.可变参数区别:定义函数时,有时候我们不确定调用的时候会多少个参数,j就可以使用可变参数
可变参数主要有两类:
*args: (positional argument) 允许任意数量的可选位置参数(参数),将被分配给一个元组, 参数名前带*,args只是约定俗成的变量名,可以替换其他名称
**kwargs:(keyword argument) 允许任意数量的可选关键字参数,,将被分配给一个字典,参数名前带**,kwargs只是约定俗成的变量名,可以替换其他名称
*args 的用法
args 是用来传递一个非键值对的可变数量的参数列表给函数
语法是使用 符号的数量可变的参数; 按照惯例,通常是使用arg这个单词,args相当于一个变量名,可以自己定义的
在上面的程序中,我们使用* args作为一个可变长度参数列表传递给add()函数。 在函数中,我们有一个循环实现传递的参数计算和输出结果。
还可以直接传递列表或者数组的方式传递参数,以数组或者列表方式传递参数名前面加(*) 号
理解* * kwargs
**kwargs 允许你将不定长度的键值对, 作为参数传递给函数,这些关键字参数在函数内部自动组装为一个dict
下篇详细讲解 *args, **kwargs 的参数传递和使用敬请关注
python
有一个相应的特殊解构器(destructor)方法名为__del__()。然而,由于python具有垃圾对象回收机制(靠引用计数),这个函数要直
到该实例对象所有的引用都被清除掉后才会被执行。python中的解构器是在实例释放前提供特殊处理功能方法,它们通常没有被实现,因为实例很少被显式释
放。
#!/usr/bin/env python
#coding=utf-8
class P():
def __del__(self):
pass
class C(P):
def __init__(self):
print 'initialized'
def __del__(self):
P.__del__(self)
print 'deleted'
c1 = C()
c2 = c1
c3 = c1
print id(c1), id(c2), id(c3)
del c1
del c2
del c3