常用内置函数
>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34
>>> max(1, 2)
2
>>> max(2, 3, 1, -5)
3
>>> int('123')
123
>>> int(12.34)
12
>>> float('12.34')
12.34
>>> str(1.23)
'1.23'
>>> str(100)
'100'
>>> bool(1)
True
>>> bool('')
False
>>> hex(100)
'0x64'
定义函数
def my_abs(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
pass
pass可以用来定义空函数
def fn():
pass
也可以用来当做占位符
if(x>1):
pass
导入math库
import math
def move(x, y, step, angle=0):
nx = x + step * math.cos(angle)
ny = y - step * math.sin(angle)
return nx, ny
默认参数
def power(x, n=2):
print(x,n)
当默认参数是引用时,如果每次调用都使用默认参数,则默认参数引用时不变的
>>> def test(a=[]):
... a.append(1)
... return a
...
>>> test()
[1]
>>> test()
[1, 1]
>>> test()
[1, 1, 1]
>>>
可变参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuplex
>>> def calc(*numbers):
... sum = 0
... for n in numbers:
... sum = sum + n * n
... return sum
...
>>> calc(1,2,3)
14
>>>
可以在一个数组前加一个*号将数组变成可变参数
>>> nums = [1, 2, 3]
>>> calc(*nums)
14
>>>
关键字参数
关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
>>> def person(name, age, **kw):
... print('name:', name, 'age:', age, 'other:', kw)
...
>>> person('lisong','18',sex='man',city='hunan')
name: lisong age: 18 other: {'sex': 'man', 'city': 'hunan'}
>>>
和可变参数类似,也可以先组装出一个dict,然后,用**把该dict转换为关键字参数传进去
>>> other={'sex':'man','city':'hunan'}
>>> person('lisong','18',**other)
name: lisong age: 18 other: {'sex': 'man', 'city': 'hunan'}
>>>
命名关键字参数
命名关键字参数用来限制关键字参数的名字,需要使用一个*号来分割,代表后面的参数为命名关键字参数
>>> def person(name, age, *, city, sex):
... print(name,age,city,sex)
...
>>> person('lisong',18,sex='man',city='hunan')
lisong 18 hunan man
此时仍然可以使用**把dict转换为关键字参数传进去
>>> other={'sex':'man','city':'hunan'}
>>> person('lisong',18,**other)
lisong 18 hunan man
>>>
参数的组合
>>> def f1(a, b, c=0, *args, **kw):
... print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
...
>>> f1('a','b','c',d='d',e='e')
a = a b = b c = c args = () kw = {'d': 'd', 'e': 'e'}
>>>
>>> def f2(a, b, c=0, *, d, **kw):
... print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
...
>>> f2('a','b',d='d',e='e')
a = a b = b c = 0 d = d kw = {'e': 'e'}
>>>
递归函数
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
如果n太大,很容易造成堆栈溢出。其实所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
上面的fact(n)
函数由于return n \* fact(n - 1)
引入了乘法表达式,所以就不是尾递归了。要改成尾递归方式,需要多一点代码,主要是要把每一步的乘积传入到递归函数中:
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)
可以看到,return fact_iter(num - 1, num * product)
仅返回递归函数本身,num - 1和num \* product
在函数调用前就会被计算,不影响函数调用。
fact(5)
对应的fact_iter(5, 1)
的调用如下:
===> fact_iter(5, 1)
===> fact_iter(4, 5)
===> fact_iter(3, 20)
===> fact_iter(2, 60)
===> fact_iter(1, 120)
===> 120
尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。