基本上所有的高级语言都支持函数, Python 也不例外, 而且其内部也内置了很多函数, 可以直接调用.
调用函数
首先要知道函数的名称和参数, 如果参数个数错误会报错(TypeError)
- abs(12,34)# 取绝对值函数
- Traceback (most recent call last):
- File "E:/phyton/pythoncode/print.py", line 1, in <module>
- abs(12,34)
- TypeError: abs() takes exactly one argument (2 given)
函数的数据类型不被接受也会报错
- abs("a")
- Traceback (most recent call last):
- File "E:/phyton/pythoncode/print.py", line 1, in <module>
- abs("a")
- TypeError: bad operand type for abs(): 'str'
函数调用出错最方便快捷的解决方式就是看错误信息
可以把函数名赋值给一个变量相当于给函数起了一个别名
a = abs a(-1) 1
定义函数
定义函数使用 def 语句, 依次是函数名, 括号, 括号中写参数, 冒号, return 语句
执行到 return, 函数执行完毕, 并返回结果, 没有 return 语句执行完函数返回 None,return None 可以简写为 return
- def my_abs(x):
- if x>= 0:
- return x
- else:
- return -x;
- my_abs(-9)
- 9
定义空函数, 使用 pass 语句, 其什么也不做, 起占位作用, 如果没有 pass 则会报错
- def nop ():
- SyntaxError: unexpected EOF while parsing
- def nop ():
- pass
- # 不报错
参数检查 Python 解释器可以自动检查出参数个数不同, 却无法检查参数的类型不对. 我们可以使用内置函数 isinstance()实现
- def my_abs(x):
- if not isinstance (x,(int,float)):
- raise TypeError('bad operand type')
- if x>=0:
- return x
- else:
- return -x;
- my_abs("a");
- Traceback (most recent call last):
- File "E:/phyton/pythoncode/print.py", line 8, in <module>
- my_abs("a")
- File "E:/phyton/pythoncode/print.py", line 3, in my_abs
- raise TypeError('bad operand type')
- TypeError: bad operand type
返回多个函数, 实际上是返回一个 tuple, 而多个变量同时接受一个 tuple 则按位置赋给对应的值
- def move(x,y,spend):
- nx = x + spend
- ny = y + spend
- return nx,ny
- x,y = move(10,10,6)
- print(x,y)
- 16 16
- r = move(10,10,6)
- print(r)
- (16,16)
函数的参数
Python 函数定义非常简单, 灵活度却非常大, 除了必选参数, 还有默认参数, 可变参数和关键字参数
默认参数
- # 默认参数, 计算 x 的 n 次方, 默认是平方
- def power(x,n=2):
- s=1;
- while n> 0:
- n = n-1
- s = s*x
- return s
写参数时, 变动大多的参数写在前面, 变动小的写在后面, 必选参数写在前面, 默认参数写在后面
函数有多个默认参数, 可以根据参数顺序填写默认参数, 也可以加参数名填写默认参数
默认参数使用起来比较简便, 但是也存在问题如:
- def add_end(L=[]):
- L.append("end");
- return L
- # 初次调用
- add _end();
- ['end']
- # 再次调用
- add_end();
- ['end','end']
原因: Python 在定义函数的时候, 默认参数 L 就被计算出来了, 既 [], 因为默认参数也是一个变量, 指向对象[], 如果调用该函数, 改变了[] 的内容, 下次调用该函数是, 默认参数的内容就变了, 所以默认参数一定要指向不变对象.
解决方法:
- def add_end(L=None):
- if L is None:
- L=[]
- L.append('end')
- return L
不变对象一旦创建, 对象内部的数据就不能修改, 这样就减少了, 由于数据修改产生的错误, 如果可以, 尽量把对象设计成不变对象.
可变参数
传入的参数可以是 0 到 n 任意个, 这些参数在函数调用时自动组装成一个 tuple.
- # 可变参数
- def calc(*numbers):
- sum=0;
- for n in numbers
- sum = sum+n;
- return sum
- #list 或 tuple 变成可变参数传入
- nums = [1,2,3]
- calc(*nums)
- 6
关键字参数
允许传入 0 到 n 个含参数名的参数, 这些关键字参数在函数内部自动组装成一个 dict
- def person (name,age,**kw):
- print('name:',name,'age:',age,'other:',kw)
- person('ice',20,city='BeiJing')
- name:ice age:20 other:{'city':'BeiJing'}
- # 传入 dict
- extra = {'city':'Beijing','job':'teacher'}
- person('ice',20,**extra)
- name:ice age:20 other:{'city':'BeiJing','job':'teacher'}
- #kw 是 extra 的一份拷贝, 对其改变不影响 extra
应用场景: 在用户注册是, 账号, 密码为必填项, 而其他信息可以选填这是就用到了关键字参数.
名命关键字参数
用于限制关键字参数的名字
- # 用 * 将位置参数和命名关键字参数分隔开
- person(name,age,*,city,job):
- # 如果含有可变参数, 这不用 * 分割
- person(name,age,*args,city,job)
命名关键字必须传入参数名, 否则报错
person('ice',20,city = 'beijing',job = 'teacher')
递归函数
- # 计算阶乘
- def fact(n):
- if n = 1:
- return 1
- return n * fact(n-1)
优点逻辑简单清晰
缺点在调用中使用栈(stack), 过深调用会出现栈溢出现象
来源: http://www.jianshu.com/p/b23abd4d8148