1. 函数的形参和实参:
定义函数时的参数为形参,调用函数时的参数为实参。下例中,para1为形参,10为实参
def func1(para1):
area = 3.14*para1**2
return area
s = func1(10)
print(s)
314.0
2. 函数文档:写函数文档是个好习惯。最好使用三引号,方便换行
函数文档可以让别人更好地理解自己的函数,注意和注释是有区别的。可以使用func.__doc__ 获取函数的文档。
def func1(para1):
"""获取圆的半径para1,返回圆的面积area"""
# 此处PI取3.14
area = 3.14*para1**2
return area
print(func1(10))
print(func1.__doc__)
314.0
获取圆的半径para1,返回圆的面积area
注意:以#号开头的不是文档,是注释,func.__doc__方法无法获取注释内容。
文档要出现在函数的第一行(前面可以有注释。),出现在其他地方不是文档,__doc__方法无法获取。
def func2(para1):
# 此处PI取3.14
"获取圆的半径para1"
area = 3.14*para1**2
"返回圆的面积area"
return area
print(func2(10))
print(func2.__doc__)
314.0
获取圆的半径para1
def func2(para1):
# 此处PI取3.14
area = 3.14*para1**2
"获取圆的半径para1,返回圆的面积area"
return area
print(func2(10))
print(func2.__doc__)
314.0
None
3. 参数定制赋值
有时,函数参数较多,传入实参时容易弄乱顺序,造成计算错误,如下实例,第二次调用func3(2,3,5)弄错了底和高,导致面积计算错误。可使用关为每个形参指定赋值。如
def func3(d1,d2,h):
"计算梯形面积,d1是上底,d2是下底,h是高"
s = (d1 + d2) * h * 0.5
return s
#计算上底为3,下底为5,高为2的梯形面积
print(func3(3,5,2))
print(func3(2,3,5))
print(func3(h=2,d1=3,d2=5))
8.0
12.5
8.0
4. 默认参数:部分函数的参数可以事先设置一个默认值,如果不传入此参数,代表使用默认值。
def func1(para1 = 10):
"获取圆的半径para1,返回圆的面积area"
# 此处PI取3.14
area = 3.14*para1**2
return area
print(func1())
print(func1(5))
314.0
78.5
5. 位置参数:参数前加*,形如*args,代表要传入的参数是一个元组, 长度不定
def func4(a,b,*args):
sum1 = 0
sums2 = a + b
print(type(args))
for i in range(len(args)):
sum1 += args[i]
return sum1,sums2
print(func4(2,3,4,6,7))
<class 'tuple'>
(17, 5)
注意:在位置参数后还要传入其他参数,需在调用时指定赋值, 否则会报错。
def func5(*args,a,b):
sum1 = 0
sums2 = a + b
for i in range(len(args)):
sum1 += args[i]
return sum1,sums2
print(func5(2,3,4,6,7))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-19-061daa652241> in <module>()
6 sums += args[i]
7 return sum1,sums2
----> 8 print(func5(2,3,4,6,7))
TypeError: func5() missing 2 required keyword-only arguments: 'a' and 'b'
print(func5(2,3,4,a=6,b=7))
(9, 13)
6. 关键字参数:形如**kwargs,代表要传入的参数是一个字典, **kwargs允许你将不定长度的键值对作为参数传递给一个函数.
def func6(**kwargs):
sent1 = ''
for key in kwargs.keys():
sent1 += ' '
sent1 += kwargs[key]
return sent1
myDict = {0:'LBJ',1:'will',2:'win',3:'another',5:'champion'}
print(func6(w1 = 'LBJ', w2 = 'will', w3 = 'win', w4 = 'another', w5 = 'champion'))
LBJ will win another champion
print(func6(myDict))
TypeError Traceback (most recent call last)
<ipython-input-49-b51c5b98f1f2> in <module>()
----> 1 print(func6(myDict))
TypeError: func6() takes 0 positional arguments but 1 was given
7. 函数与过程:有返回值称为函数,没有返回值称为过程,python严格来说只有函数,没有写return时,默认返回None.
def func4(a,b,*args):
sum1 = 0
sums2 = a + b
for i in range(len(args)):
sum1 += args[i]
print(func4(2,3,4,6,7))
None
8. 函数变量的作用域:局部和全局变量;函数中可以随意访问全局变量.
(1) 但修改全局变量需注意,python会创建一个新的局部变量代替,名字和全局变量一样(屏蔽的方式)。所以一般不要试图在函数内部修改全局变量。
def func7(price,discount=0.7):
print("原有价格",price,'变量id是',id(price))
new_price = price*discount
price = 89
print("修改后的价格1",price,'变量id是',id(price))
return new_price
price = 99
print("折后价格",func7(price))
print("修改后的价格2",price,'变量id是',id(price))
原有价格 99 变量id是 1683944976
修改后的价格1 89 变量id是 1683944656
折后价格 69.3
修改后的价格2 99 变量id是 1683944976
(2)若确实想在函数中修改全局变量,可借用global
def func7(discount=0.7):
global price
print("global使用测试开始...")
print("原有价格",price,'变量id是',id(price))
new_price = price*discount
price = 89
print("修改后的价格1",price,'变量id是',id(price))
return new_price
price = 99
print("折后价格",func7(price))
print("修改后的价格2",price,'变量id是',id(price))
price = 99
print("折后价格",func7(price))
print("修改后的价格2",price,'变量id是',id(price))
注意:global变量是不必也不能作为函数参数的, 否则可能出错
def func7(price,discount=0.7):
global price
new_price = price*discount
return new_price
price = 99
print("折后价格",func7(price))
File "<ipython-input-9-5af6c32b3c4a>", line 2
global price
^
SyntaxError: name 'price' is parameter and global
(3)内嵌函数:func2嵌套在func1函数中,这就是内嵌函数
内部函数整个作用域都在外部函数之内,内部函数可以随意访问外部函数的变量/参数
def func1():
print("func1函数被调用")
def func2():
print("func2函数被调用")
func2()
func1()
func1函数被调用
func2函数被调用
(4)闭包:一种函数式编程范式。
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。如下例子:内部函数funcY调用了外部函数的临时变量x, 而外部函数funcX返回funcY的引用。
def funcX(x):
def funcY(y):
return x + y
return funcY
z = funcX(1)
print(type(z))
print(z(3))
print(funcX(5)(7))
<class 'function'>
4
12
(5)nonlocal的使用
def funcX():
x = 8
def funcY():
x *= x
return x
return funcY()
funcX()
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-28-09432caee8da> in <module>()
6 return funcY()
7
----> 8 funcX()
<ipython-input-28-09432caee8da> in funcX()
4 x *= x
5 return x
----> 6 return funcY()
7
8 funcX()
<ipython-input-28-09432caee8da> in funcY()
2 x = 8
3 def funcY():
----> 4 x *= x
5 return x
6 return funcY()
UnboundLocalError: local variable 'x' referenced before assignment
内部函数对外部函数的局部变量进行修改时,需注意陷阱,如上实例, 道理和全局变量 VS 局部变量类似。使用nonlocal可解决
def funcX():
x = 8
def funcY():
nonlocal x
x *= x
return x
return funcY()
funcX()
64