写博客的初衷就是希望自己能坚持吧,当作一个小打卡啦~ ps:大神绕路,很初级很白痴
同时记录一些易错和易忘的知识点,以后复习翻着看看。
另:廖雪峰老师的网站刚刚接触,感觉很干货的样子,在这里推荐一下下~
注:本博客参考廖雪峰老师的网站
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
day3:
一、调用函数
1.可以直接从Python的官方网站查看文档:
http://docs.python.org/3/library/functions.html
也可以在交互式命令行通过help(abs)查看abs函数的帮助信息。
2.调用函数的时候,如果传入的参数不对,会报TypeError的错误。
3.常用函数——数据类型转换
>>> s=int('123')
>>> b=s/2
>>> b
61.5
二、定义函数
1.在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。
def my_abs(x):
if x >= 0:
return x
else:
return -x
2.实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。
3.参数检查
调用函数时,如果参数个数不对,Python解释器会自动检查出来,并抛出TypeError;
但是如果参数类型不对,Python解释器就无法帮我们检查。
我们可以通过修改my_abs的定义,对参数类型做检查,只允许整数和浮点数类型的参数。数据类型检查可以用内置函数isinstance()实现:
isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()
isinstance(object, classinfo) //如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。
>>> 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 "<input>", line 1, in <module>
File "<input>", line 3, in my_abs
TypeError: bad operand type
4.返回多个值
import math
def move(x,y,step,angle=0):
nx=x+step * math.cos(angle)
ny=y-step * math.sin(angle)
return nx,ny
x, y = move(100, 100, 60, math.pi / 6)
print(x, y)
Python的函数返回多值其实就是返回一个tuple,但写起来更方便。
>>> r = move(100, 100, 60, math.pi / 6)
>>> print(r)
(151.96152422706632, 70.0)
三、函数的参数
1.位置参数:必须传入的参数
例:计算x的平方
def power(x): //x即为位置参数
return x * x
2.默认参数:用于简化函数的调用
注:(1)默认参数不能放在必选参数前面
(2)当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
这样,当我们调用power(5)时,相当于调用power(5, 2),调用n不等于2时又恢复原样:
>>> power(5)
25
>>> power(5, 2)
25
>>> power(5,3)
255
(3)定义默认参数要牢记一点:默认参数必须指向不变对象!或者用None修改可变对象为不变对象来实现
def add_end(L=None):
if L is None:
L = []
L.append('END')
return L
>>> add_end()
['END']
>>> add_end()
['END']
3.可变参数
可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。
定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数。
//给定一组数字a,b,c……,请计算a2 + b2 + c2 + ……
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum
>>> calc(1, 2, 3)
14
>>> calc(1, 3, 5, 7)
84
>>> nums = [1, 2, 3] //Python允许在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:
>>> calc(*nums)
14
3.关键字参数
可变参数 允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple;
关键字参数 允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict,可以扩展函数的功能。
def person(name, age, **kw):
print('name:', name, 'age:', age, 'other:', kw)
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
和可变参数类似,也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去:
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
4.命名关键字参数
如果要限制关键字参数的名字,就可以用命名关键字参数。
注:命名关键字参数必须传入参数名。
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*了。
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)
5.参数组合
参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
对于任意函数,都可以通过类似func(*args, **kw)的形式调用它,无论它的参数是如何定义的。
错题:试写一个累乘函数
//错误示范
# -*- coding: utf-8 -*-
def product(*nums):
multi=1
for n in nums:
multi=multi*n
return multi
#测试
print('product(5) =', product(5))
print('product(5, 6) =', product(5, 6))
print('product(5, 6, 7) =', product(5, 6, 7))
print('product(5, 6, 7, 9) =', product(5, 6, 7, 9))
if product(5) != 5:
print('测试失败!')
elif product(5, 6) != 30:
print('测试失败!')
elif product(5, 6, 7) != 210:
print('测试失败!')
elif product(5, 6, 7, 9) != 1890:
print('测试失败!')
else:
try:
product()
print('测试失败!')
except TypeError:
print('测试成功!')
product(5) = 5
product(5, 6) = 30
product(5, 6, 7) = 210
product(5, 6, 7, 9) = 1890
测试失败!
错误原因:测试中try:函数中至少要有一个必选参数,才能测试成功
def product(x,*nums):
s=x
for i in nums:
s*=i
return s
product(5) = 5
product(5, 6) = 30
product(5, 6, 7) = 210
product(5, 6, 7, 9) = 1890
测试成功!
四、递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
1.使用递归函数需要注意防止栈溢出,由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
2.针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。
Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。
尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。