观察自己设置的绝对值函数(my_abs)和内置函数abs的报错区别:
def my_abs(x): if x>=0: return x else: return -xmy_abs('A')
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-1-3a70387458fd> in <module> 5 return -x 6 ----> 7 my_abs('A')<ipython-input-1-3a70387458fd> in my_abs(x) 1 def my_abs(x):----> 2 if x>=0: 3 return x 4 else: 5 return -xTypeError: '>=' not supported between instances of 'str' and 'int'
abs('A')
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-2-6eee3e7a739d> in <module>----> 1 abs('A')TypeError: bad operand type for abs(): 'str'
观察上方的报错信息,内置函数abs会检查参数错误而我们自己定义的函数不会,所以我们的函数定义不够完善。
对my_abs的定义进行修改,只允许整数和浮点数类型的参数,进行数据类型的检查。
isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
isinstance()语法规范:isinstance(object, classinfo)
classinfo:可以是直接或间接类名、基本类型或者由它们组成的元组。
#添加参数检查def my_abs(x): if not isinstance(x,(int,float)): raise TypeError('bad operand type') if x>=0: return x else: return -xmy_abs('A')
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-3-f13543a1b7d8> in <module> 7 else: 8 return -x----> 9 my_abs('A')<ipython-input-3-f13543a1b7d8> in my_abs(x) 2 def my_abs(x): 3 if not isinstance(x,(int,float)):----> 4 raise TypeError('bad operand type') 5 if x>=0: 6 return xTypeError: bad operand type
返回多个值import mathdef move(x,y,step,angle = 0): nx = x+steP*math.cos(angle) ny = y-steP*math.sin(angle) return nx,ny#import math语句表示导入math包,也就是导入相应sin和cos之类的数学函数x,y = move(100,100,60,math.pi/6)print(x,y)
151.96152422706632 70.0
其实这是一种返回多个值的假象,实际上python函数返回的是一个tuple,多个变量可以同时接收一个tuple,按位置赋给对应的值。
练习定义一个函数quadratic(a,b,c),接收三个参数,返回一元二次方程的两个解
计算平方根调用math.sqrt()函数:
import mathdef quadratic(a,b,c): d = b*b-4*a*c if d>=0: x1 = (-b+math.sqrt(d))/(2*a) x2 = (-b-math.sqrt(d))/(2*a) return x1,x2 else: return '此方程无解'quadratic(1,2,1)
(-1.0, -1.0)
2、函数的参数定义函数接口的基本要求:确定参数的名字和位置即可。
位置参数编写计算某数平方的函数
def power(x): return x*xprint(power(5))print(power(10))
25100
以上代码中,x为位置参数,调用函数必须传入对应个数的位置参数
编写计算x^n的函数
def power(x,n): s = 1 while n > 0: n = n-1 s = s * x return sprint(power(5,2))print(power(5,3))
25125
传入位置参数时不仅要保证个数相同,还要保证和定义函数时候的顺序也相同(直接用函数名的话可以忽略顺序)
默认参数给幂设置默认值
def power(x,n=2): s = 1 while n>0: n = n-1 s = s*x return sprint(power(5))print(power(5,2))
2525
设置默认参数的注意事项:
(1)必选参数在前,默认参数在后。
(2)当函数有多个参数时,把变化大的参数放在前面,变化小的参数放在后面(变化小的参数就可以作为默认参数)
设置默认参数的好处:降低调用函数的难度。
学生注册问题:来自相同的城市,拥有相同的年龄,只有名字和班级不一样。
def enroll(name,gender,age=6,city='Beijing'): print('name',name) print('gender',gender) print('age',age) print('city',city)enroll('Sarah','F')
name Sarahgender Fage 6city Beijing
定义默认函数时候的注意点:默认参数必须指向不变对象
例如:如果默认参数指向一个列表,在运行函数时会将列表看作一个变量,改变列表的内容后下次调用函数列表的初始内容就会发生改变。
可以使用None这种不变对象来设置默认参数值。
def add_end(L = []): L.append('END') return Ladd_end()add_end()add_end()
['END', 'END', 'END']
可变参数定义具有可变参数的函数,必须确定输入参数。
可变参数在函数调用时自动组装成为一个tuple。
定义可变参数比定义一个List或tuple参数相比,仅仅在参数前加了一个 * 号。在函数内部,可以传入任意个参数,包括0个参数。
def calc(*numbers): sum = 0 for n in numbers: sum = sum+n*n return sumprint(calc(1,2))print(calc())
50
关键字参数关键字参数允许传入0个或任意个含参数名的参数,这些关键字参数被自动组装成一个dict。
函数除了需要接受必须参数外,还可以接受关键字参数kw,传入关键字参数后会以字典的形式呈现出来
def person(name,age,**kw): print('name:',name,'age:',age,'other:',kw)print(person('Michael',30))print(person('Bob',35,city='Beijing'))
name: Michael age: 30 other: {}Nonename: Bob age: 35 other: {'city': 'Beijing'}None
关键字参数可以扩展函数功能,接收到调用者提供的更多参数(例如必填项之外的选项)
** +字典名表示把字典内所有的key-value用关键字参数传入到函数 ** kw参数中,kw仅仅是dict的一份拷贝。
命名关键字参数限制关键字参数的名字,需要用命名关键字参数,在参数之间加上特殊的分隔符 * 即可,分隔符后面的参数即为命名关键字参数。
def person(name,age,*,city,job): print(name,age,city,job)person('Jack',24,city='Beijing',job='Engineer')
Jack 24 Beijing Engineer
如果函数定义中已经含有可变参数,那么不需要分隔符,只需要在可变函数后加上命名关键字参数即可。
def person(name,age,*args,city,job): print(name,age,args,city,job)person('Jack',24,city = 'Beijing',job='Engineer')
Jack 24 () Beijing Engineer
函数参数的定义顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
def f1(a, b, c=0, *args, **kw): print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)def f2(a, b, c=0, *, d, **kw): print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
3、递归函数求阶乘的函数 f(n) = n! = 1×2×3×⋅⋅⋅×(n−1)×n=(n−1)!×n=f(n−1)×n
所以f(n)可以表示为n * f(n-1)
def f(n): if n ==1: return 1 return n*f(n-1)print(f(1))print(f(5))print(f(100))
112093326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
使用递归函数可能会导致栈溢出的问题(调用次数过多的时候)
解决递归调用栈递归的方法是尾递归优化
尾递归:在函数返回的时候调用自身本身,且return语句不能包括表达式,能够让递归函数只使用一个栈帧,不出现栈溢出。上面的f(n)在return语句中使用了乘法表达式,不能算作尾递归。
def fact_iter(num,product): if num==1: return product return fact_iter(num-1,num*product)fact_iter(5,1)
120
上述为尾递归调用,大多数编程语言没有针对尾递归的优化,python也没有,所以即使将f(n)修改成尾递归方式也会导致栈溢出
总结以上是内存溢出为你收集整理的Python基础语法快速复习-函数全部内容,希望文章能够帮你解决Python基础语法快速复习-函数所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)