1. 函数调用
python在调用函数的时候,注意到形参的类型以及形参的个数是否和已知函数参数相匹配, 函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”,相当于C语言里面引用操作,给函数取了一个别的名字。
>>> a = abs # 变量a指向abs函数
>>> a(-1) # 所以也可以通过a调用abs函数1
2. 自定义函数:
定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。
def my_abs(x):
if x >= 0:
return x
else:
return -x
假设已经写好了上述函数,而且将这个文件保存为abstest.py,那么我们如果想要调用我们自己写的函数,我们可以利用语句:
from abstest import my_abs
进行调用我们写的函数
2.1 空函数
作为一个占位符,如果我们写的代码的,可以利用pass,表示啥也不做,但是不可以去掉,否则就不正确了
def grade_function(x):
x = int(x)
if x > 90:
return x
else:
pass # 这里的pass是作为占位符出现的,表示什么也不做,仅仅占了一个位置,为以后写
grade = input('input grade')
print(grade_function(grade))
自己定义的函数使用的时候,如果参数的个数是不对的话,那么会自动帮我们检测错误,但是如果参数的类型是不正确的话,他产生的错误是不完善的,这时候我们需要增加一层判断机制。使用isinstance()内置函数帮我们检查是否产生错误,然后我们在使用raise TypeError抛出异常。
def my_abs(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x
最后在注意一点,Python表面看起来是可以返回多个值的,其实他是返回了一个Tuple元组
3. 函数的参数种类:
3.1 默认参数
假设首先定义了一个函数pow(n)表示计算n^2,那么现在我们想要定义一个n^3,那么我们重新定义一个函数pow(n,3),那么此时这个pow(n)函数就会失效,那么我们假如还想使用以前的pow(n)函数怎么办了,我们可以通过使用默认参数,既可以使用扩展的进行调用,也可以使用原来最基本的函数。这个默认参数就好像是以前的默认的选项一样。
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s
>>> power(5)
25>>> power(5, 3)
125
这个演示例子表示我们不仅仅可以使用扩展的函数,有时候方便起见,也可以使用不是扩展之后函数。
- 一是必选参数在前,默认参数在后,否则Python的解释器会报错;
- 二是如何设置默认参数。
当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数。
使用默认参数有什么好处?最大的好处是能降低调用函数的难度。 - 最后在使用默认参数的时候注意默认参数需要时不可变参数类型
3.2 可变参数
顾名思义:可变参数就是参数的个数是可变的,从原来的函数参数使List或者Tuple变成了*这样就可以传入很多个参数了。
定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。
如果现在已经已知一个List和Tuple了,我们可以在调用的时候加上了一个*表示把List和Tuple变成可变参数传入
def cal_grade(number): 这是通过传入参数是List
sum = 0
for n in number:
sum = sum + n
return sum
print(cal_grade([1,2,3]))
def cal_grade(*number): # 这个是传入可变参数
sum = 0
for n in number:
sum = sum + n
return sum
List = [1,2,3,4]
print(cal_grade(1,2,3,4)) # 这是正常调用可变参数的
print(cal_grade(*List)) # 如果想要传入已经确定的list或者Tuple的话,我们可以使用*将其变换成可变参数形式
3.3 关键字参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
关键字参数的作用是什么?如果你想提供一个用户注册的功能,那么现在你可以提供基本的参数设置,但是你也可以提供其他的参数设置,你也可以提供成为一个字典,通过这个关键字将字典作为关键字参数传入。**
def print_student(age, name, **kw):
print('age:', age, 'name:', name, 'others:', kw)
student = {'s1': 18, 's2': 'xuchao'}
print_student(11, '11', **student)
3.4 命名关键字参数
对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些,就需要在函数内部通过kw检查,这时候我们可以使用命名关键字参数帮助我们解决哪些参数才可以进行正确的传入。
def student(age, name, *, city):
print(age, name, city)
student(12, 'X11', city='ee') # 这里city在命名关键字里面,所以这句代码是没有问题的
student(12, 'X11', house='ee') # 但是这里house是不在这个里面的,所以是不正确的关键字参数
3.5 递归函数
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
针对尾递归优化的语言可以通过尾递归防止栈溢出。尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。
Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。