这一篇介绍函数。
一、函数知识概述
1. 关于函数
(1)函数是组织好的,可重复使用的实现复杂功能的代码块;
(2)python提供了很多内建函数,比如print,但我们经常需要自己写函数来实现自己想要的功能,这叫做用户自定义函数;
(3)说一下关于C++和python文件函数和代码执行的差别。二者的每个cpp文件和.py文件都可以定义多个功能函数,但cpp文件可执行的内容都在main函数里,所以main函数调用了哪些函数就执行哪些;python的.py文件文件没有main函数,所以它的执行是逐行执行,除去def定义的函数其他的都逐行执行,def函数是调用了就执行,不调用就不执行,且二者共同点函数要放在调用语句的前面,即先定义,再使用;
2. python定义一个函数
按照以下规则定义一个函数:
(1)函数代码块以def关键词开头,后面接函数名和括号();
(2)圆括号之间用于定义传入参数;
(3)一般函数内部第一行语句用来注释,即说明函数功能;
(4)函数内容以冒号:开始,并且缩进;
(5)以return [表达式] 结尾,表达式可有可无,不带表达式相当于返回None;
示例如下:
def printme(str):
'''
这是若干行注释:
打印任何输入的字符串
'''
print(str)
return
str1='zhuge'
printme(str1)
输出示例:
zhuge
二、参数传递
在python中,类型属于对象,变量没有类型,变量指向某一个对象,代表对这个对象的引用。
1. 可更改对象与不可更改对象
在python中,string、tuples和numbers是不可更改的对象,而list和dict是可以更改的对象。
(说明:因为前者要变值就要重新赋值,后者可以添加元素。重新赋值就是新的引用了,就是新的对象,而后者添加元素时,指向的对象还是那个对象,但是对象的内容变了)
2. python函数的参数传递
(1)不可变类型:类似于C++的值传递。如整数,字符串,元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身;
(2)可变类型:类似于C++的引用传递,如如列表,字典。如 fun(list),则是将list真正传过去,fun 函数内部修改 list 的值后外部的 list 也会受到影响;
总的来说,python中一切都是对象,所以不能说是值传递还是引用传递,应该说传不可变对象和传可变对象。
三、参数
一般来说,参数传递会有以下问题:
(1)参数顺序乱了怎么办;
(2)参数数量不够怎么办;
(3)参数的值怎么分配;
当然,前两个问题在C++里不会存在,因为C++传入和传出参数顺序,数量和类型必须严格保持一致,不然就会出错。第三个问题都可能会有,这时会有默认参数。
参数一般有以下类型:必备参数,关键字参数,默认参数,不定长参数。
1. 必备参数
必备参数必须以正确的顺序和数量传入函数,跟声明时一样。不然会出现语法错误:
def printme(str):
print(str)
return
str1='zhuge'
printme()
输出:
Traceback (most recent call last):
File "E:/py_code/Drug-Drug-Interaction-Prediction-master/parctice.py", line 7, in <module>
printme()
TypeError: printme() missing 1 required positional argument: 'str'
2. 关键字参数
函数调用使用关键字参数来确定传入的参数值,此时允许参数顺序传递时和声明时不一致,因为python能够自动匹配,如下:
def printme(s1,s2):
print(s1)
print(s2)
return
str1='zhuge'
str2='12'
printme(s2=str2,s1=str1)
输出:
zhuge
12
3. 默认参数
调用函数时,如果值没有传入,则被认为是默认值:
def printinfo(name='wood', age=35):
"打印任何传入的字符串"
print(name)
print(age)
return
printinfo(age=50, name="Mike")
printinfo(name="Tom")
输出:
Mike
50
Tom
35
一般使用默认参数和关键字参数结合使用,防止错误。
4. 不定长参数
有时你可能需要一个函数处理比声明时更多的参数,即你不知道传入有多少个参数,这叫做不定长参数。此时声明时使用加星号*的变量来存放他们。语法如下:
def functionname([formal_args,] *var_args_tuple ):
"函数_文档字符串"
function_suite
return [expression]
举例如下:
def printinfo(arg1, *vartuple):
"打印任何传入的参数"
print(arg1)
for var in vartuple:
print(var)
return
输出:
10
70
60
50
四、匿名函数
python使用lambda来创建匿名函数。
(1)lambda只是一个表达式,函数体比def简单很多。
(2)lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
(3)lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
(4)虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
语法如下:
lambda [arg1 [,arg2,.....argn]]:expression
实例:
sum = lambda arg1, arg2: arg1 + arg2
# 调用sum函数
print(sum(10, 20))
print(sum(20, 20))
输出:
30
40
总结:
(1)学会怎么简单定义一个函数,即首先写def 函数名(参数1,参数2):函数体,最后return结尾;
(2)注意参数为可变对象与不可变对象时对参数本身的影响,总的来说就是参数为不可变对象时等价于值传递,函数内改变参数值对参数本身没有影响;为可变对象时等价于引用传递,函数内改变参数值会对参数本身产生影响;
(3)注意区别python和C++中变量与对象的差别:即python中的变量没有类型,只有对象才有类型,变量仅是对某个对象的引用;
(4)进行函数调用时,一般使用关键字引用,即方便自己观察和使用,也防止参数顺序变化引起的错误;同时对于可能不用的参数进行默认参数的赋值(一般都赋给默认参数);
(5)还有一点关于全局变量,局部变量的知识,以及return,跟C++一样,所以没说。
难点与重点:
在这里说一下python中的对象和变量,参数的问题。
先来说一句话,在python中,类型属于对象,变量是没有类型的(因为变量仅仅是一个引用)。
在python中,所有的参数都是引用。变量是没有类型的,它仅仅是一个名字,对象才具有类型。比如list类型的对象,string类型的对象,这些都是对象,他们具有类型。但变量没有类型,其只是对一个对象的引用(一个指针),它可以指向一个list类型的对象,也可以指向string类型的对象。当a=5时,这里生成了一个int值的对象5,并让a指向了它。再有a='hello',这里生成了一个string类型的对象,让a指向了它,以前的5则被丢弃。
这就是python与C++的区别,C++里的变量它是有类型的,定义时要提前说明,变量也占用了内存位置,内存中存的是这个变量的值;python中的变量仅仅是一个引用,指向它引用的对象,其内存的位置存的是引用对象的地址。