一.函数形参和实参的区别
- 形参的全称是形式参数,在用def关键字定义函数时函数名后面括号里的变量称为形式参数。
- 实参全称为实际参数,在调用函数时提供的值或者变量称为实际参数。
def add(a, b): # 这里的a和b是形参
return a + b
add(1, 2) # 这里的1和2是实参
二.参数的传递
- 首先明确:Python中一切皆为“对象”,变量中存放的是对象的引用。
x = 2
y = 2
print(id(2)) # id返回对象的内存地址
print(id(x))
print(id(y))
z = 'abc'
print(id('abc'))
print(id(z))
- 在Python 中参数传递采用的是值传递,和c语言有点相似。在绝大多数情况下,在函数内部直接修改形参的值不影响实参。
def add(a, b):
print(id(a)) # 输出4304251648
a = a + b # 将a+b的值赋给a
print(id(a)) # 输出4304251712
print(a) # 输出5
a = 3
print(id(a)) # 输出4304251648
b = 2
add(3, 2)
print(id(a)) # 输出4338555648
print(a) # 输出3
- 还有一些特殊情况,可以通过特殊的方式在函数内部修改实参的值。
def modify1(m, K):
m = 2
K = [4, 5, 6]
return
def modify2(m, K):
m = 2
K[0] = 0 # 同时修改了实参内容
return
n = 100
L = [1, 2, 3]
modify1(n, L)
print(n, L) # 输出100 [1, 2, 3]
modify2(n, L)
print(n, L) # 输出100 [0, 2, 3]
注意:modify1并为修改实参内容,K = [4, 5, 6]相当于下图过程,对L没有产生影响。
- 例:在函数内部修改实参
def modify3(v, item):
v.append(item)
a = [2]
modify3(a, 3)
print(a) # 输出[2, 3]
注意:可变对象可以修改实参值,不可变对象不能修改实参值。
三.函数参数的类型
(1)默认值参数:可以给函数提供默认值。
def display(a='hello', b='world'):
print(a + b)
display() # 输出helloworld
display(b='python') # 输出hellopython
display(a='hello') # 输出helloworld
display('python') # 输出pythonworld
(2)关键字参数:避免了需要牢记位置参数顺序的麻烦。
def display(a, b):
print(a + ' ' + b)
display('hello', 'world') # 输出hello world
display('world', 'hello') # 输出world hello
# 下面两条语句效果相同
display(a='world', b='hello') # 输出world hello
display(b='hello', a='world') # 输出world hello
(3)任意个数参数:一般情况下在定义函数的时候,函数参数的个数是确定的,但是某些情况下我们不能确定参数个数。这时候只需要在参数前面加上’*‘或者’**’。
def fruitname(category, *names):
print('种类是%s' % category, end=' ')
if names:
print('包括:', end='')
for name in names:
print(name, end=' ')
print('')
fruitname('水果')
fruitname('水果', '苹果')
fruitname('水果', '苹果', '橘子')
- *和**都能表示接受0到任意多个参数。
- 其中*表示将没有匹配的值都放在同一个 元组 中。
- **则表示将没有匹配的值都放在一个 字典 中。
def demo(*p):
for item in p:
print(item, end='')
demo(1, 2, 3) # 输出123
def demo(**p):
for item in p.items():
print(item, end='')
demo(x=1, y=2, z=3) # 输出('x', 1)('y', 2)('z', 3)
(4)将函数作为参数传给另一个函数。这里涉及到了装饰器雏形。
def hi():
print('hi')
def doSomethingBeforeHi(func):
print('Doing Work Before Hi()',end=' ')
func()
doSomethingBeforeHi(hi) # 输出Doing Work Before Hi() hi
四.变量的作用域
- 引入函数的概念之后,就会出现变量的作用域问题。变量的作用域即变量起作用的范围。
- 一个变量在函数外部定义和在函数内部定义,其作用域是不同的。
- 有时候还可以使用特殊的关键字改变一个变量的作用域。
Python中变量的作用域共有四种:
1.Local:函数内的区域,包括局部变量和参数。
2.Enclosing:外面嵌套函数的区域,常见的是闭包函数的外层函数。
3.Glogbal:全局作用域。
4.Built-in:内建作用域。
- Python中变量采用L->E->G->B的规则查找,即Python检索变量的时候,会优先在局部作用域查找,如果没找到,便会去局部外的区域查找(例如闭包),再找不到就去全局作用域中找,最后去内建作用域中找。
(1)局部变量:在函数内定义的,只在该函数内起作用,称为局部变量。即使在函数外有个相同名字的变量,他们也没有任何关系。也就是说在函数内定义的变量作用域只在函数内。函数结束,自动删除。
(2)全局变量:在函数外部定义的,作用域是整个程序。全局变量可以直接在函数里面使用,但是如果要在函数内部改变全局变量值,必须用global关键字进行声明。
def fun():
global x # 如果在函数内部对全局变量进行修改,Python会把此变量当作局部变量
x = x + 1 # 为了使全局变量生效 可以在函数内使用global关键字进行声明 不声明就修改会报错
print(x, end=' ')
fun()
print(x, end=' ') # 输出3 3
(3)global关键字:使用global关键字修饰的变量,之前可以不存在。
def fun1():
global x
x = 2
print(x, end=' ')
def fun2():
global x
x = x + 1
print(x, end=' ')
def fun3():
x = 4
x = x + 1
print(x, end=' ')
fun1()
fun2()
fun3()
print(x, end=' ') # 输出2 3 5 3
(4)nonlocal关键字:在一个嵌套的函数中修改嵌套作用域的变量。注意:使用nonlocal关键字修饰的变量在嵌套作用域中必须已经存在。
def fun():
count = 1
def fun_in():
nonlocal count
count = 12
fun_in()
print(count)
fun() # 输出12