函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
1、定义一个函数
你可以定义一个自己想要的功能的函数,规则是:
- 函数代码块以
def
关键词开头,后接函数标识符名称和圆括号() - 任何
传入参数
和自变量
必须放在圆括号中间
,圆括号之间可以用于定义参数 - 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以
冒号起始
,并且缩进
。 - return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回
None
。
2、语法
python定义函数使用def关键字,一般格式如下:
def 函数名(参数列表):
函数体
实例
①、使用函数输出hello python
def hello():
print("hello python")
hello()
②、更复杂点的应用,函数中带上参数变量
#计算面积函数
def area(width,height):
return width*height
def printwelcome(name):
print("Welcome",name)
printwelcome("justin")
w=4
h=5
print("width=",w,"height=",h,"area=",area(w,h))
3、函数调用
这个例子调用了printme()函数
def printme(str):
print(str)
return
#调用函数
printme("调用用户自定义函数")
printme('再次调用同一函数')
4、参数传递
①在python中,类型属于对象,变量是没有类型的:
a=[ 1, 2, 3 ]
a=" python "
这个代码,[1,2,3]是List类型,"python"是String类型,而变量a没有类型,它只是一个对象的引用(一个指针)
,可以是指向List类型对象,也可以是指向String类型对象
②可更改(mutable)与不可更改(immutable)对象
在python中,string、tuples、numbers是不可更改的对象,而list、dict等是可以修改的对象
补充一下:
为什么有些可以更改,有些是不可更改的:
存储空间保存的数据允许被修改就是可变类型,反之,就是不可变类型
当你创建一个列表或者字典,你对列表或字典的某个值进行修改时,它的内存地址依然是刚开始的地址,没有改变。
list=[1,2,3]
print(id(list))
list[2]=6
list.pop(0)
print(id(list))
说明修改列表(字典也一样),其内存地址不改变,说明了列表、字典是可变的
但当你对数字、元组、字符串修改时,存储空间改变了
a="hhhhh"
print(id(a))
a="jjjj"
print(id(a))
c=3
print(id(c))
c=5
print(id(c))
说明"="赋值运算时重新为变量找了一个新的内存地址,而不是修改原来的内存数据
-
不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a。
-
可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
python 函数的参数传递:
-
不可变类型:类似 c++ 的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。
-
可变类型:类似 c++ 的引用传递,如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后fun外部的la也会受影响
python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
③传不可变对象实例:
def hhh(a):
a=10
b=2
hhh(b)
print(b) #输出结果为 2
④传可变对象实例:
可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了
def hhh(list1):
list1.append([1,2,3,4])
print("函数内取值:",list1)
return
list1=[10,20,30]
hhh(list1)
print("函数外取值:",list1)
传入函数的和在末尾添加新内容的对象用的是同一个引用
5、参数
以下是调用函数时可使用的正式参数类型:
- 必需参数
- 关键字参数
- 默认参数
- 不定长参数
①必须参数
必须参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样
def hhh(a):
print(a)
return
hhh()
这种情况下会报错,hhh函数括号内必须有参数
②关键字参数
使用关键字参数允许函数调用时参数的顺序与声明时不一致
def hhh(a):
print(a)
return
hhh(a="justin")
以下实例中演示了函数参数的使用不需要使用指定顺序:
def hhh(name,age):
print("名字:",name)
print("年龄:",age)
return
hhh(age=17,name="justin")
③默认参数
调用函数时,如果没有传递参数,则会使用默认参数
def hhh(name,age=18):
print("名字:",name)
print("年龄:",age)
hhh(age=17,name="justin")
hhh(name="lalala")
④不定长参数
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数
基本语法
def functionname([formal_args,] *var_args_tuple ):
function_suite
return [expression]
加了星号 *
的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。
def hhh(a,*b):
print(a)
print(b)
hhh(1,2,3,4)
如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量
def hhh(a,*b):
print("输出:")
print(a)
for x in b:
print(x)
return
hhh(10)
hhh(1,2,3)
还有一种就是参数带两个星号 **
基本语法
def functionname([formal_args,] **var_args_dict ):
function_suite
return [expression]
加了两个星号 **
的参数会以字典的形式导入
def hhh(a,**b):
print(a)
print(b)
hhh(a=2,b=3,c=7,d=8)
声明函数时,参数中星号 * 可以单独出现
例如:
def f(a,b,*,c):
return a+b+c
如果单独出现星号 * 后的参数必须用关键字传入,例如:
def hhh(a,*,b):
print(a)
print(b)
hhh(2,b=3)
6、匿名函数
python 使用 lambda
来创建匿名函数。
所谓匿名,意即不再使用 def语句这样标准的形式定义一个函数。
- lambda 只是一个表达式,函数体比 def 简单很多。
- lambda的主体是一个表达式,而不是一个代码块。 仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
- 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
语法:
lambda [arg1 [,arg2,.....argn]]:expression
实例:
sum= lambda a,b:a+b
print(sum(2,3)) #输出5
7、return语句
return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式
def hhh(a,b):
print("函数内:",a+b)
#return a+b
yy=hhh(10,20)
print("函数外:",yy)
def hhh(a,b):
print("函数内:",a+b)
return a+b
yy=hhh(10,20)
print("函数外:",yy)
8、强制位置参数
Python3.8 新增了一个函数形参语法 / 用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。
在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 或 f 要求为关键字形参:
def hhh(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
hhh(10, 20, 30, d=40, e=50, f=60) #正确