廖雪峰老师python教程https://www.liaoxuefeng.com/wiki/1016959663602400
小甲鱼python教程:https://www.bilibili.com/video/av27789609?from=search&seid=697360651657412999
python支持非常灵活定义的函数,而且本身内置了很多有用的函数。
函数最基本的一种代码抽象方式。
https://docs.python.org/3/library/functions.html
python有提供了很多内置函数,使用方法可以在官网查询。也可以使用help(abs)查看abs函数的帮助文档
TypeError 错误会反应参数错误。
max() and min() 可以有多个参数
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”
>>> i=int
>>> i(1.2)
1
定义一个函数要使用def
语句,依次写出函数名、括号、括号中的参数和冒号:
,然后,在缩进块中编写函数体,函数的返回值用return
语句返回。
x=input('your name:')
def my_hello(x):
return 'hello '+x
print(my_hello(x))
注意,如果没有return 语句,会返回None。return None 简写为return
将my_hello()的函数定义保存为hello.py文件后,在该文件目录下,可以使用 from hello import my_hello
()不需要.py扩展名)可以导入my_hello()函数
>>> from hello import my_hello
>>> my_hello('wenjunjie')
'hello wenjunjie'
空函数:用pass语句作为占位符
数据类型检查可以使用内置函数isinstance()实现;
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
形如 return a,b
实际返回的是一个元祖,但在语法上,返回一个元祖可以省略括号,多个变量可以同时接受一个tuple,按位置赋值给对应的值。
c,d=move(…)
1.必选参数在前,默认参数再后
2.变化大的参数放前面,变化小的放在后边
def enroll(name, gender, age=6, city='Beijing')
enroll('Bob', 'M', 7)
enroll('Adam', 'M', city='Tianjin')
定义默认参数要牢记一点:默认参数必须指向不变对象!
def calc(*numbers): #定义,内部来说还是组装了一个元祖
calc(1,2,3,4,5...) #使用
calc(*nums) #nums是一个list或tuple 当要传入list或者tuple时候在变量前加*
def person(name, age, **kw): #定义
print('name:', name, 'age:', age, 'other:', kw)
person('Adam', 45, gender='M', job='Engineer')#使用
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'} #结果
person('Jack', 24, **extra) #extra为元祖时
**extra
表示把extra
这个dict的所有key-value用关键字参数传入到函数的**kw
参数,kw
将获得一个dict,注意kw
获得的dict是extra
的一份拷贝,对kw
的改动不会影响到函数外的extra
def person(name, age, *, city, job): #定义
print(name, age, city, job)
person('Jack', 24, city='Beijing', job='Engineer') #调用
命名关键字参数需要一个特殊分隔符*
,*
后面的参数被视为命名关键字参数。
命名关键子可以有缺省值(默认值)
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
对于任意函数,都可以通过类似func(*args, **kw)
的形式调用它,无论它的参数是如何定义的。
虽然可以组合多达5种参数,但不要同时使用太多的组合,否则函数接口的可理解性很差
小练习
题目:求一个或多个数的乘积
def product(x,*y):
ans=x
for i in y:
ans=ans*i
return ans
使用*args
和**kw
是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。
函数在内部调用自己本身就是递归函数。逻辑清晰
解决栈溢出的方法,尾递归优化。
尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。
小练习
汉诺塔问题
def move(n,a,b,c):
if n==1:
print(a,'-->',c)
else:
move(n-1,a,c,b)
move(1,a,b,c)
move(n-1,b,a,c)
move(3, 'A', 'B', 'C')
>>> def fun1(x): #一般定义函数
... return 2*x+1
>>> g=lambda x:2*x+1 #使用lambda表达式
使用lambda表达式的目的
补充BIF
filter(function,iterator):过滤器iterator。一次迭代iterator中的元素,该元素经过function,如果返回true加入到结果,否则被过滤掉。
>>> list(filter(lambda x:x%2,range(20)))
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
map(fun,iterator):映射。将iterator中的元素依次作为fun的参数,经过处理的结果加入到结果序列中
>>> list(map(lambda x:x**2,range(10)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]