在交互式环境定义函数时,空格前面会出现三个点…,这时按两此回车才能返回控制行。 如果是内建函数(不是自己定义的),如果传入的参数不符合函数要求,会报TypeError错误,可能有两种原因1.参数数量不对 2.参数类型不符 但是如果是自己定义的函数,在函数调用的时候不会在传参数的时候报错,而是在运行的时候报错,这时候如果想要判断出来在传入参数的时候出现问题需要自己写代码来处理。例如: if not isinstance(x, (int, float)): raise TypeError(‘bad operand type’) 函数可以返回多个参数,但是实际上是返回了一个tuple,如
def doublere ( a, b) :
return a+ b, a- b
a, b= doublere( 1 , 2 )
实际上返回了( a,b) 这个元组,所以不是返回了多个值,仍然是返回了一个值(tuple )。
def register ( name, age, city= 'bj' ) :
xxxxxxxx
xxxxxxxx
这个时候如果我们调用函数
register( 'liming' , 11 ) 没有问题,会将city默认为bj。如果想更改默认参数的话,可以
register( 'liming' , 11 , 'shanghai' )
当有多个默认参数的时候,为避免混淆可以在调用的时候在默认参数前面加上字段名。如:
register( 'liming' , 11 , city= 'shenzhen' )
def add ( a, l= [ ] ) :
l. append( a)
add( 1 )
add( 2 )
猜这时候l里面是2 呢还是1 ,2 .
答案是1 ,2
因为因为默认参数L也是一个变量,它指向对象[ ] ,每次调用该函数,如果改变了L的内容,
则下次调用时,默认参数的内容就变了,不再是函数定义时的[ ] 了。
def calc ( numbers) :
sum = 0
for n in numbers:
sum = sum + n * n
return sum
上述代码必须传入一个list ,但是组装一个list 很麻烦(或者tuple ),我们更加喜欢calc(1 ,2 )这种方便的用法(在某些场合)。所以我们就可以引入可变参数
def calc ( * numbers) :
sum = 0
for n in numbers:
sum = sum + n * n
return sum
这样接受的就是一个tuple ,calc(1 ,2 )就ok,如果还行传入一个list 或者tuple 的话,可以在传入参数前面也加一个* 例如
list1= 【1 ,2 ,3 】
calc(* list1)
def person ( name, age, ** kw) :
print ( 'name:' , name, 'age:' , age, 'other:' , kw)
关键字参数允许你传入0 个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
person( 'Bob' , 35 , city= 'Beijing' )
name: Bob age: 35 other: { 'city' : 'Beijing' }
亦可以在外面定义一个字典,然后传参的时候在前面加** 和上面可变参数例子一样
函数递归容易爆栈,但是用尾递归可以巧妙地解决爆栈的问题。而且不影响可读性(因为用循环来取代递归很麻烦,不如递归代码来的清晰).解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。例如:
def fact ( n) :
return fact_iter( n, 1 )
def fact_iter ( num, product) :
if num == 1 :
return product
return fact_iter( num - 1 , num * product)
// // // // // // //
def fact ( n) :
if n== 1 :
return 1
return n * fact( n - 1 )
这样的话因为有表达式所以就不是尾递归了。