Python函数
Posted 礁之
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python函数相关的知识,希望对你有一定的参考价值。
文章目录
此文章参考廖雪峰大神的官方:调用函数 - 廖雪峰的官方网站 (liaoxuefeng.com)
一、什么是函数
- 函数通俗的来讲,就是一段固定的代码,函数还可以传入参数,最终得到的结果其实就固定代码的执行结果。
- python中内置了许多函数,我们可以直接进行调用,并且我们自己也可以自定义函数
二、调用函数
- python内置了许多函数,我们可以直接进行调用
- 如果要调用函数的话,需要先知道函数的函数名称以及可以传入参数的数量和数据类型等,可以去pyton的官网进行查询:查询python内置函数
- 也可以在python交互模式中使用
help()
函数来查看指定函数的相关信息
>>> help(abs)
Help on built-in function abs in module builtins:
abs(x, /)
Return the absolute value of the argument.
- 调用函数时,如果传入的参数数量、数据类型不对的话,会报错,以求绝对值函数
abs()
为例:
>>> abs(1,2,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: abs() takes exactly one argument (3 given)
>>> abs(1)
1
>>> abs("1")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bad operand type for abs(): 'str'
#例如求最大值函数max这种函数,可传入的参数数量就和abs不同
>>> max(1,23,4,5)
23
- 除了上述的max和abs,python内置的常用函数还包括数据类型转换的函数,下面来看几个例子:
>>> int('123') #转换字符串为数字
123
>>> int(12.33) #转换浮点数为整数
12
>>> str(123) #转换数字为字符串
'123'
>>> bool(1) #转换数字为布尔值
True
>>> list('aaa') #转换字符串为列表
['a', 'a', 'a']
- 函数还可以指向其他变量:
>>> a = abs
>>> a(-1)
1
>>> abs(-1)
1
三、定义函数
- 定义函数可以使用
def
语句,依次写出def 函数名(参数):
,输入回车,在缩进块中编写代码,函数的返回值使用return
语句返回 - 以一个计算数字平方的函数示例:
- 交互环境中:
>>> def test(x): #输入:后会有...提示符,输入代码后连续两次回车可以返回>>>提示符下
... return x * x
...
>>> test(2)
4
>>> test(22)
484
- 写入py文件中:
# -*- coding: utf-8 -*-
def test(x):
return x * x
print(test(2))
print(test(22))
#输出
4
484
-
要注意的是,在函数中的语句执行时,只要遇到了
return
语句时,就代表函数执行完毕,并且返回执行结果,如果一个函数中没有return
语句,函数也会返回值,但是这个值是None
,return
没有指定返回值也会返回None
,也就是说return None
可以写成return
-
如果想要定义的函数什么都不做,可以使用
pass
语句:
>>> def test(x):
... if x > 10:
... return x
... else:
... pass
...
>>> test(20)
20
>>> test(9)
>>>
#pass语句表示什么都不做,可以作为占位符,例如函数的代码还没想好怎么写,就可以
- 如果还想让函数返回多个值的话,可以这样做:
# -*- coding: utf-8 -*-
def test(i):
x = i + 1
y = i - 1
return x,y
print(test(20))
#输出:
(21, 19)
四、函数的参数
- 在定义函数的时候,我们需要把函数参数的名字、数量、位置确定下来,在确定下来之后,函数的接口其实也就定义完成
- 对于函数调用者来说,想要使用函数只需要知道如何传递正确的参数、参数的数量、参数的类型等,以及调用函数后会返回什么值,这样就已经足够了,而函数中间的逻辑算法等,调用者是不用去了解的
- Python函数的定义简单、灵活度大,除了正常定义的必选参数外,还可以使用
默认参数
、可变参数
和关键字参数
,使得函数定义出来的接口,不但能够处理复杂的参数,还可以简化调用者的代码
1、位置参数
1、我们先来定义一个计算x二次方的函数:
>>> def test(x):
... return x * x
...
在test函数中,变量x就是位置参数,当我们要调用test函数时,必须传入x参数,并且只能传输一个,下面来看调用test参数时传入不同参数时的输出的结果
>>> print(test(4)) #传入整数
16
>>> print(test(4.5)) #传入浮点数
20.25
>>> print(test('4')) #传入字符串,发现报错了,因为字符串无法使用 “ * ” 进行运算
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in test
TypeError: can't multiply sequence by non-int of type 'str'
>>> print(test(4,5)) #传入两个参数,同样报错,因为test函数中只有一个位置参数
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: test() takes 1 positional argument but 2 were given
>>> print(test()) #不传入任何参数,因为test函数中必须传入一个参数x,所以报错了
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: test() missing 1 required positional argument: 'x'
2、现在来优化test参数,使之可以计算x的n次方:
>>> def test(x,n):
... i = 1
... while n > 0:
... n = n -1
... i = i * x
... return i
...
>>> print(test(7,3))
343
在优化后的test函数中,多了一个参数n,那么在每次调用test函数时,就需要两个数字类型的参数,传入的参数按照x和n的前后顺序依次传入,例如test(7,3),则x=7,n=3
2、默认参数、
- 从上面说的位置参数来看,我们可以知道在调用函数时传入参数的
数量
、数据类型
都必须正确,否则会报错。 - 以优化后可以计算x的n次方函数test为例,如果我们需要多次调用test函数,而每次参数n的值都是2时,我们需要每次调用函数都传入两个参数,这样调用的话,我们会传入很多重复的参数,而默认参数就可以帮助我们减少重复操作
1、定义test函数,可以计算x的n次方,默认计算是x的2次方
>>> def test(x,n=2):
... i = 1
... while n > 0:
... n = n - 1
... i = i * x
... return i
...
>>> print(test(3,2))
9
>>> print(test(3))
9
从调用test函数可以看出,默认n的参数没有传入时,n=2
2、在使用默认参数时,默认参数必须要指向不变对象,即不可变类型,下面来看一个案例:
>>> def aaa(L=[]):
... L.append('end')
... return L
...
>>> print(aaa([1,2,3]))
[1, 2, 3, 'end']
>>> print(aaa(['x','y','a']))
['x', 'y', 'a', 'end']
>>> print(aaa())
['end']
>>> print(aaa())
['end', 'end']
>>> print(aaa([1,2,3]))
[1, 2, 3, 'end']
从上面的案例可以看出,在定义aaa参数时使用了L=[ ]作为默认参数,在我们正常调用aaa函数,传入列表参数时,输出的结果都是正常的,而在没有传入参数,使用aaa函数的默认参数时,我们发现在调用两次后,输出的结果并不是我们想的一个end,而是又添加了一个end,这是因为在定义函数时,默认参数L的值就已经被计算出来了,因为L也算一个变量,它指向了对象[ ],在每次调用时,如果修改了L的内容(即修改了空列表[ ]),则在下次调用时,L会变成修改后的值(即修改后的列表['end']),所以会输出这种结果
而解决的方法其实可以加一个if判断例如:
>>> def aaa(L=None):
... if L is None:
... L = []
... L.append('end')
... return L
...
>>> print(aaa())
['end']
>>> print(aaa())
['end']
>>> print(aaa([1,2,3]))
[1, 2, 3, 'end']
定义L的默认值为None,当L等于None时,才会定义一个空列表,这样就可以避免上面的情况
在定义默认参数时需要注意:
- 函数的参数传入是通过前后顺序,所以在定义默认参数时,要把必选参数放在前面,默认参数放在后面,否则会造成
必须参数的值错误的传入了默认参数,而必须参数没有传入值,从而报错
- 默认参数必须指向不可变类型,避免不必要的错误
3、可变参数
- 在python中,还可以定义可变参数
1、定义一个函数test,当传入的函数为a,b,c时,test函数可以计算a*a+b*b+c*c
>>> def test(number):
... sum = 0
... for i in number:
... sum = sum + i * i
... return sum
...
>>> print(test([1,2,3,4]))
30
>>> print(test((7,3,15,4)))
299
上面定义的test函数虽然可以达到效果,但是在每次调用函数时,传入的参数需要先组装成一个列表或者元组
2、使用可变参数优化后:
>>> def test(*number):
... sum = 0
... for i in number:
... sum = sum + i * i
... return sum
...
>>> print(test(1,2,3,4))
30
>>> print(test([1,2,3,4]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in test
TypeError: can't multiply sequence by non-int of type 'list'
>>> print(test())
0
>>> l = [1,2,3,4]
>>> print(test(l[0],l[1],l[2],l[3]))
30
>>> print(test(*l))
30
可以看到test函数的参数number前面加了一个 “ * ” ,在调用函数时无需组装成列表或元组,直接使用逗号隔开即可,可以传入任意数量的参数,包括0个参数,但是这样我们想要传入列表时就会报错,我们可以先定义列表,然后同样使用” * “来把列表传入函数
4、关键字参数
- 上面的可变参数允许传入
0个或者任意数量
的参数,传入的参数在函数调用时会自动组装成一个元组
,而关键字参数允许传入0个或者任意数量的包含参数名
的参数,这样参数会自动组装成一个字典
1、利用关键字参数定义函数test
>>> def test(name,age,**id):
... print('name:',name,'age:',age,'id:',id)
...
>>> print(test('zhangsan',22)) #在只传入前两个参数时,可以看到最后一个参数id输出了一个空字典
name: zhangsan age: 22 id:
None
>>> print(test('zhangsan',22,id=2223))
name: zhangsan age: 22 id: 'id': 2223
None
>>> print(test('zhangsan',22,id=2223,other=5553)) #传入两个key=value
name: zhangsan age: 22 id: 'id': 2223, 'other': 5553
None
>>> aaa = 'id':2223,'other':5553 #定义一个aaa字典
>>> print(test('zhangsan',22,id=aaa['id'],other=aaa['other'])) #传入字典时,使用下标调用
name: zhangsan age: 22 id: 'id': 2223, 'other': 5553
None
>>> print(test('zhangsan',22,**aaa)) #和关键字参数一样,可以使用**一次性传入字典,需要注意的是,利用关键字参数把aaa字典传入到test函数中的**id参数,id参数会得到一个字典,而id的值只是aaa值的一份拷贝而已,修改id并不会影响aaa的值
name: zhangsan age: 22 id: 'id': 2223, 'other': 5553
None
- 对于关键字参数来说,我们可以传入任意不受限制的关键字参数,而具体的值,需要在函数内部通过带
**
的参数(即**id
)来检查
5、命名关键字参数
1、以上面的test函数为例,现在我们需要检查传入的参数是否有id和other参数,可以这样写:
>>> def test(name,age,**id):
... if 'id' in id:
... pass
... if 'other' in id:
... pass
... print('name:',name,'age:',age,'id:',id)
...
>>> print(test('zhangsan',22,id=2222,other=3333,io=4444))
name: zhangsan age: 22 id: 'id': 2222, 'other': 3333, 'io': 4444
None
#但是发现我们仍然可以传入其他的参数,如果想要达到上面的效果,对传入的参数进行限制,我们可以使用命名关键字参数,例如:
>>> def test(name,age,*,id,other):
... print('name:',name,'age:',age,'id:',id,'other:',other)
...
>>> print(test('zhangsan',22,id=3333,other=4444))
name: zhangsan age: 22 id: 3333 other: 4444
None
>>> print(test('zhangsan',22,id=3333,other=4444,io=5555)) #可以看到使用命名关键字参数后,除了id和other,继续传入io参数时会报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: testPython基础03-函数详解