1.定义一个函数
定义一个函数的规则:
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
函数内容以冒号 : 起始,并且缩进。
return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。
函数格式:
def 函数名(参数列表):
函数体
return 返回值
def fn():
print('Hello World!')
fn()
2.函数参数
参数是函数的输入,它们可以是可选的或必需的。
Python函数支持以下类型的参数:
必需参数:这些参数在函数调用时必须提供,没有默认值。
默认参数:这些参数有默认值,如果调用时不提供值,则使用默认值。
可变参数:函数可以接受不定数量的参数。可以通过*args(接受任意数量的位置参数)和**kwargs(接受任意数量的关键字参数)来实现。
关键字参数:这些参数在调用函数时使用关键字来传递。
2.1 必需参数
必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
def fn1(x):
print(x*2)
fn1(10)#20
def fn2(x,y):
print(x*2,y)
fn2(10,20)#20 20
def fn3(x,y):
print(x+y)
fn3(10)#报错
def fn4(x):
print(x*3)
fn4(10,20)#报错
2.2 关键字参数
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。
使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
def fn1(x,y):
print(x,y)
fn1(100,y=200)#100 200
def fn2(x,y):
print(x,y)
fn2(y=100,x=200)#200 100
2.3 默认参数
调用函数时,如果没有传递参数,则会使用默认参数, 默认参数必须写在必须参数后面。
def fn1(x,y=0):
print(x,y)
fn1(100)#100 0
def fn2(x=0,y=1):
print(x,y)
fn2()#0 1
#错误的函数设计:默认参数没有写在必须参数后面
def fn3(x=0,y):
print(x,y)
2.4 不定长参数
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数
def function_name( [formal_args,] *var_args_tuple ):
加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数。
def fn1(x,y,*arg):
print(x,y,arg)
fn1(10,20,30,40,50)#10 20 (30, 40, 50)
如果在函数调用时没有传入不定长参数,它就是一个空元组。我们也可以不向函数传递未命名的变量
def fn1(x,y,*arg):
print(x,y,arg)
fn1(10,20)#10 20 ()
如果传参的时候也是元组,可以使用*进行解包
def fn1(x,y,*arg):
print(x,y,arg)
tup1=(30,40,50)
fn1(10,20,tup1)#10 20 ((30, 40, 50),)
fn1(10,20,*tup1)#10 20 (30, 40, 50)
加了两个星号 ** 的参数会以字典的形式导入(了解)。
def printinfo(x, **dic):
print (x,dic)
printinfo(1, a=2,b=3)#1 {'a': 2, 'b': 3}
printinfo(1, y=2,z=3)#1 {'y': 2, 'z': 3}
声明函数时,参数中星号 * 可以单独出现。
如果单独出现星号 *,则星号 * 后的参数必须用关键字传入
def f(a,b,*,c):
print(a+b+c)
f(1,2,c=3) # 正常:6
f(1,2,3) # 报错:f() takes 2 positional arguments but 3 were given
2.5 强制位置参数
用 / 来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。
用 * 来指明函数形参必须使用关键字参数,不能使用指定位置参数的形式。
在以下的例子中,形参 a 和 b 必须使用指定位置参数,c 或 d 可以是位置形参或关键字形参,而 e 和 f 要求为关键字形参:
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
以下使用方法是正确的:
f(10, 20, 30, d=40, e=50, f=60)#正确的用法
f(10, b=20, c=30, d=40, e=50, f=60) # b 不能使用关键字参数的形式
f(10, 20, 30, 40, 50, f=60) # e 必须使用关键字参数的形式
2.6 可变不可变
可更改(mutable)与不可更改(immutable)对象
在python中,strings,tuples和numbers是不可更改的对象,而list,dict等则是可以修改的对象。
不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变 a 的值,相当于新生成了 a。
可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。
python 函数的参数传递:
不可变类型:值传递: 如整数、字符串、元组。如 fun(a),传递的只是 a 的值,没有影响 a 对象本身。如果在 fun(a) 内部修改 a 的值,则是新生成一个 a 的对象。
可变类型:引用传递: 如 列表,字典。如 fun(la),则是将 la 真正的传过去,修改后 fun 外部的 la 也会受影响
python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。
传不可变对象实例
通过内置的 id() 函数来查看内存地址变化:
def change(a):
print(id(a))
a=10
print(id(a))
a=1
print(id(a))
change(a)
#总结:可以看见在调用函数前后,形参和实参指向的是同一个对象(对象 id 相同),在函数内部修改形参后,形参指向的是不同的id。
传可变对象实例
可变对象在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。
def changeme(mylist):
mylist.append(40)
print (mylist)
mylist = [10,20,30]
changeme(mylist)#[10, 20, 30, 40]
print (mylist)#[10, 20, 30, 40]
#总结:传入函数的和在末尾添加新内容的对象用的是同一个引用
3.返回值
函数可以使用return
语句来返回一个或多个值。
如果没有明确的return
语句,函数将默认返回None
。
#没有return
def fn1():
print("调用了fn1()函数")
re=fn1()
print(re)
#返回一个值
def fn2(x):
return x+100
re2=fn2(100)
print(re2)
#返回多个值
def fn3(x):
return x*x,x%3
re3=fn3(10)
print(re3)