文章目录
函数定义和调用
函数定义
- 函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码段。
- 使用函数能提高应用的模块性、代码的重用率和可读性。
'''
用户自定义函数的一般格式为:
def 函数名([参数1, 参数2, ... ])
"""函数说明"""
函数体
其中:
1. 函数关键字:函数以关键字 def 开头,后接函数名和圆括号()。
2. 函数名:遵循表示符命名规则。函数名最好是有意义的名称,以增加可读性。
3. 参数:必须放在圆括号中间,称为形式参数(简称形参)。形参是可选的,可以没有,也可以有多个。当有多个形参时,各形参之间用逗号隔开。
4. 函数说明:函数第一行语句可以选择性地使用字符串文档,用于存放函数说明
5. 函数内容:以冒号起始,并且缩进
6. 返回值:使用“return [表达式]” 结束函数,返回一个值给调用方。如果没有 “return [表达式]”,函数默认返回 None。当函数返回多个值时,其本质上是把这些值作为一个元组返回,如 "return 2,3,4" 实际上返回的是元组(2,3,4)
7. 函数体:当函数体为 pass 语句时,表示什么工作也不做,如抽象类中的抽象函数
8. python 中的所有缩进均使用一个 Tab 键或 4个空格,但是上下文的缩进应使用同一种方式,不可以掺杂使用。
'''
# 定义一个输出 “Hello world” 的函数
def SayHello():
""" # 这种字符串文档写法只需要在 Pycharm 中输入三次引号,回车即可
输出 “Hello world”
:return: None
"""
print("Hello world!")
# 函数没有返回值就不写
- 在 Python 中,函数可以有自己的成员,也可以为函数动态的增加和删除成员。
- 需要注意的是,在函数外面删除函数内部定义的成员是无效的。
'''
错误案例:为什么在命令行方式下可以删除内部成员 myFunc.a,难道还是在函数内部吗,有知道的小伙伴留言哦,感谢!有点懵住了!
'''
# 函数内部成员的使用
>>>
>>> def myFunc():
... myFunc.a = 100
... print("myFunc.a = %d, myFunc.b = %d." % (myFunc.a, myFunc.b))
...
>>> muFunc()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'muFunc' is not defined. Did you mean: 'myFunc'?
>>> y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
>>> myFunc()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in myFunc
AttributeError: 'function' object has no attribute 'b'
>>> myFunc.b = 200
>>> myFunc()
myFunc.a = 100, myFunc.b = 200.
>>> del myFunc.b
>>> myFunc.b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'b'
>>> myFunc()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in myFunc
AttributeError: 'function' object has no attribute 'b'
>>> del myFunc.a
>>> myFunc.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'a'
>>>
'''
在 Pycharm 中发现确实是不能删去 内部成员 myFunc.a 的
'''
# 函数内部成员的使用
def myFunc():
myFunc.a = 100
print("myFunc.a = %d, myFunc.b = %d." % (myFunc.a, myFunc.b))
myFunc.b = 200
myFunc()
del myFunc.a # 会发现删过 a 之后 a 还是存在
myFunc()
del myFunc.b # b 可以删除且不会存在
myFunc()
'''
错误信息:
Traceback (most recent call last):
File "F:\python_study_csdn\demo1\function.py", line 27, in <module>
myFunc()
File "F:\python_study_csdn\demo1\function.py", line 20, in myFunc
print("myFunc.a = %d, myFunc.b = %d." % (myFunc.a, myFunc.b))
AttributeError: 'function' object has no attribute 'b'
myFunc.a = 100, myFunc.b = 200.
myFunc.a = 100, myFunc.b = 200.
'''
函数调用
- 函数调用时需要指出函数名称,并传入相应的参数。
- 函数调用时传入的参数称为实际参数(即实参)。
- 默认情况下,函数调用时传入的实参个数、顺序等必须和函数定义时形参的个数、顺序一致。
函数调用时的执行顺序如下:
- 执行函数调用前的语句
- 执行函数调用,运行被调用函数内的语句,并返回相应结果
- 执行函数调用后的语句
# 求一个梯形的面积
def echelonArea(top, bottom, height):
""" 求梯形面积函数 """
area = 1 /2 * (top + bottom) * height
return area
if __name__ == '__main__':
t = 3.6; b = 6.2; h = 4.5
area1 = echelonArea(t, b, h) # 方法1:调用函数,传入参数
print("area1 = ", area1) # area1 = 22.05
area2 = echelonArea # 方法2: 把函数对象赋给变量 area2
print("area2 = ", area2(t, b, h)) # area2 = 22.05
函数参数
参数传递
Python 中的对象可分为不可变对象(数字、字符串、元组等)和可变对象(列表、字典、集合等)。对应地,Python 函数的参数传递有以下两种情况:
- 实参为不可变对象。当实参为不可变对象时,函数调用是将实参的值复制一份给形参。在函数调用中修改形参时,不会影响函数外面的实参(传值不传址)。
- 实参为可变对象。当实参为可变对象时,函数调用是将实参的引用复制给形参。在函数调用中修改形参时,函数外面的实参也会随之变化。
# 参数传递
def Swap(x, y):
print("交换前: x = %d, y = %d." % (x, y))
x, y = y, x # 交换两个形参的值
print("交换后: x = %d, y = %d." % (x, y))
a = 5; b = 6 # 定义变量 a、b
print("调用前: a = %d, b = %d." % (a, b))
Swap(a, b)
print("调用后: a = %d, b = %d." % (a, b))
'''
结果分析:会发现第三行虽然在函数内部确实发生了交换,但是函数外面的值并没有发生改变,传值但不传址(因为常量是不可变数据类型)
调用前: a = 5, b = 6.
交换前: x = 5, y = 6.
交换后: x = 6, y = 5.
调用后: a = 5, b = 6.
'''
# 参数传递(列表)
def changeList(myList):
myList.append(4) # 在列表 myList 末尾增加一个新元素
list1 = [1, 2, 3] # 定义列表 list1
print("调用前 list1: ", list1) # 调用前 list1: [1, 2, 3]
changeList(list1)
print("调用后 list1: ", list1) # 调用后 list1: [1, 2, 3, 4]
# 会发现在调用后实际的列表多出了一个元素,这就是发生了传址行为
参数类型
调用函数时可使用的正式参数类型包括:
- 必需参数
- 关键字参数
- 默认参数(缺省参数)
- 不定长参数
必需参数
必须参数要求函数调用时传入的实参个数、顺序和函数定义时形参的个数、顺序完全一致。
# 必需参数
def myAdd(x, y, z):
return x + y + z
a = 3; b = 4; c = 5
print("调用结果: ", myAdd(a, b, c)) # 调用结果: 12
关键字参数
关键字参数在函数调用时使用形参作为关键字来确定传入的参数值,允许函数调用时实参的顺序与函数定义时形参的顺序不一致。
# 函数关键字参数
# 可写函数说明
def printinfo(name, age):
"""打印任何传入的字符串"""
print("Name:", name)
print("Age:", age)
return
# 调用printinfo函数
printinfo(age=50, name="miki")
默认参数(缺省参数)
调用函数时,如果没有传递实参,则会使用函数定义时赋予参数的默认值。
# 函数缺省参数
def printinfo(name, age=35):
"""打印任何传入的字符串"""
print("Name:", name)
print("Age:", age)
return
# 调用printinfo函数
printinfo(age=50, name="miki")
printinfo(name="miki") # 会发现使用了 age = 35
不定长参数
在实际使用中,有可能需要一个函数能处理比当初声明时更多的参数,这种参数称为不定长参数。不定长参数有如下两种形式:
- *args:将接收的多个参数放在一个元组中。
- **args:将显式赋值的多个参数放入字典中。
# 函数不定长参数
def printinfo(arg1, *vartuple):
"""打印任何传入的参数"""
print("输出: ")
print(arg1)
print("vartuple:", vartuple)
return
# 调用printinfo函数
printinfo(10)
printinfo(70, 60, 50)
def func(**args): # **args:将接收的多个参数放在一个元组中
for key, value in args.items():
print("%s:%s" % (key, value))
func(新发明1="高铁", 新发明2="扫码支付", 新发明3="共享单车")
'''
输出:
10
vartuple: ()
输出:
70
vartuple: (60, 50)
新发明1:高铁
新发明2:扫码支付
新发明3:共享单车
'''
参数传递的序列解包
参数传递的序列解包针对的是实参,有 * 和 ** 两种形式。实参前加了 * 或 ** 后会将列表、元组、字典等迭代对象中的元素分别传递给形参中的多个变量。
# 序列解包和封包
a = tuple(range(10))
print(a) # (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
# 只解出0到2,3到9保存为一个列表
b0, b1, b2, *b3 = a
print(b3) # [3, 4, 5, 6, 7, 8, 9]
# 只解出8到9,0到7保存为一个列表
*c1, c2, c3 = a
print(c1) # [0, 1, 2, 3, 4, 5, 6, 7]
# 只解出0和9,1到8保存为一个列表
c1, *c2, c3 = a
print(c2) # [1, 2, 3, 4, 5, 6, 7, 8]
- 由下例可知,当实参是字典时,可以使用 ** 对其序列解包,但字典中的键和形参在名称、个数上必须对应。
# 实例2
def func(x, y, z):
return x * 100 + y * 10 + z
print(func(*[1, 2, 3])) # 123
print(func(**{'x': 1, 'y': 2, 'z': 3})) # 123
print(func(**{'z': 1, 'y': 2, 'x': 3})) # 321
特殊函数
匿名函数
- 匿名函数是指没有函数名的简单函数,只可以包含一个表达式,不允许包含其他复杂的语句。
- 表达式的结果就是函数的返回值。
- 使用关键字 lambda 创建匿名函数。
'''
一般格式为: lambda [arg1[,arg2, ... , argn]]: expression
其中:
arg1, ..., argn:形参,可以没有,也可以有多个
expression:表达式
默认情况下,在调用匿名函数时,传入的实参个数、顺序同样要和匿名函数在定义时的形参个数、顺序一致。
'''
'''
突然想到匿名函数的基本格式是否还可以记成这样:
lambda <None> (参数):
函数体
其中:
<None>: 本来是函数名,但是现在省略不写了
函数体:把原来很长的几条语句浓缩成一条语句(如果可以的话)
'''
# 匿名函数
def calc(x, y):
return x ** y
# 换成匿名函数
calc = lambda x, y : x**y
print(calc(2, 5))
def calc(x, y):
if x > y:
return x * y
else:
return x / y
# 三元运算换成匿名函数
calc = lambda x, y :x * y if x > y else x / y
print(calc(2, 5))
# other examples
func = lambda a, b = 3, c = 2: b ** 2 - 4 * a * c # 默认参数
print(func(1))
print(func(1, 4))
list1 = [1, 2, 3]
list2 = [4, 5, 6]
sum = lambda x, y: x + y
print(sum(list1, list2))
print(list(map(lambda x, y: x + y, list1, list2)))
递归函数
-
如果一个函数在函数体中直接或者间接调用自身,那么这个函数就称为递归函数。
-
Python 允许使用递归函数。
-
如果函数 a 中调用函数 a 本身,则称为直接递归。
-
如果函数 a 调用函数 b,在函数 b 中又调用了函数 a,则称为间接递归。
举例:我们定义一个 fac(n) 函数,计算 1 + 2+ 3+ …+n 的值
通过不断调用 fac( ) 函数,直到 fac( ) 函数为一个明确值,然后再次不断向上返回结果,最后计算出 fac(n)。
通过举例可以知道递归函数的两个注意点:
- 递归函数就是在函数里调用自身。
- 递归函数必须有一个明确的递归结束条件,称为递归出口。否则,会造成程序的死循环。
# 费波纳茨数列前20项
def fib(n):
if n == 1 or n == 2:
return 1
else:
return fib(n - 1) + fib(n - 2)
sum = 0
for i in range(1, 21):
sum = sum + fib(i)
print("前20项之和为: ", sum)
递归函数相较于普通函数的优点:
- 递归函数使代码看起来更加整洁、优雅。
- 可以用递归将复杂的任务分解成更简单的子问题。
- 使用递归比使用一些嵌套迭代更容易。
但是,过多的递归也会导致递归程序存在以下不足:
- 递归的逻辑很难调试、跟进。
- 递归调用的代价高昂(效率低),占用了大量的内存和时间。
因此,当程序要求递归的层数太多时,就不适合使用递归函数完成程序了。
嵌套函数
- 嵌套函数指在一个函数(称为外函数)中定义了另外一个函数(称为内函数)。
- 嵌套函数中的内函数只能在外函数中调用,不能在外函数外面直接调用。
# 实例1
# 定义外函数
def outerfunc():
# 定义内函数
def innerfunc():
print('innerfunc') # 内函数中的语句
print('outerfunc') # 外函数中的语句
innerfunc() # 调用内函数
outerfunc() # 调用外函数
innerFunc() # 会发现报错,因为在外函数的外部调用内函数是不允许的
# 示例2
# 定义外函数
def outerfunc(x):
# 定义内函数
def innerfunc(y):
return x * y
return innerfunc # 调用内函数
print("方法一调用结果: ", outerfunc(3)(4)) # 在调用时传递外函数参数和内函数参数
a = outerfunc(3) # 调用外函数,传递外函数参数
print("方法二调用结果: ", a(4)) # 间接调用内函数,传递内函数参数
特殊内置函数
内置函数简介
内置函数(Built-In Funcitons, BIF)是 Python 内置对象雷类型之一,封装在标准库模块 __builtins __(双下划线)中,可以直接在程序中使用,如 input() 函数,print() 函数,abs() 函数等。Python 中的内置函数使用 C语言进行了大量的优化、运行速度快、推荐优先使用。
>>> help("pow")
Help on built-in function pow in module builtins:
pow(base, exp, mod=None)
Equivalent to base**exp with 2 arguments or base**exp % mod with 3 arguments
Some types, such as ints, are able to use a more efficient algorithm when
invoked using the three argument form.
部分特殊内置函数
range() 函数
range() 函数返回一个整数序列的迭代对象。
'''
一般格式为: range([start,]end[,step])
格式解读:第一种情况:必须要有 range(end),即必须要有一个结束迭代的位置,默认从0开始,到 end-1 结束,默认步长为1
第二种情况:range(start,end),即从start 开始,到 end-1 结束,默认步长为1(当start比end 大时,step为负整数)
第三种情况:range(start,end,step),从start 开始,到 end-1 结束,步长自定义,可以为负值
'''
>>> list(range(10)) # 不包括10
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(2,10)) # [2,10)
[2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(1,10,2)) # 10以内奇数,步长为2
[1, 3, 5, 7, 9]
>>> list(range(5,1,-1)) # 步长为负整数
[5, 4, 3, 2]
type()和 isinstance() 函数
- 可以使用 type() 函数或 isinstance() 函数判断一个对象的类型。
- type(object):接收一个对象 object 作为参数,返回这个对象的类型.
- isinstance(object,class) :判断接受的对象 object 是否是给定类型 class 的对象:如果是,则返回 True;否则返回 False。
# type() or isinstance()
print("'innovate 的类型是:' ", type("innovate")) # 'innovate 的类型是:' <class 'str'>
print("6是整数吗? ", isinstance(6, int)) # 6是整数吗? True
在判断一个对象类型时,type() 函数和 isinstance() 函数有如下区别:
- type() 不会认为子类对象是一种父类类型,不考虑继承关系。
- isinstance() 会认为类对象是一种父类类型,考虑继承关系。.
eval() 函数
eval() 函数用来执行一个字符串表达式,并返回表达式的值。(其实本质就是将表达式的最外层的引号去掉,让其变成一个表达式,计算出具体的值,常用于去掉最外层引号)
'''
一般格式: eval(expression[,globals[,locals]])
其中:
expression:表达式
globals:变量作用域,可选,必须是一个字典对象。
locals:变量作用域,可选,可以是任何映射(map)对象。
'''
# eval
print(eval('2 + 3')) # 返回求和结果
print(eval("['london', 'beijing', 'lasa']")) # 字符串转换为列表
a, b = eval(input("请输入两个数(用','隔开):")) # 接收从键盘输入的多个数
print("a = %d, b = %d." % (a, b))
'''
5
['london', 'beijing', 'lasa']
请输入两个数(用','隔开):1,2
a = 1, b = 2.
'''
map() 函数
map() 函数把函数依次映射到序列或迭代器对象的每个元素上,并返回一个可迭代的 map 对象作为结果。
'''
其一般格式为:map(function, iterable,...)
其中:
function:为被调用函数。
iterable:为一个或多个序列。
'''
# map
def cube(x):
return x ** 3
print(list(map(cube, [1, 2, 3, 4, 5]))) # 计算列表中各个元素的立方和
def add(x, y):
return x + y
print(list(map(add, [1, 3, 5, 7, 9], [2, 4, 6, 8 ,10]))) # 两个列表相同位置的元素相加
a, b = map(int, input("请输入两个数(用','隔开):").split(',')) # 接收从键盘输入的两个数
print("a = %d, b = %d." % (a, b))
'''
[1, 8, 27, 64, 125]
[3, 7, 11, 15, 19]
请输入两个数(用','隔开):1,2
a = 1, b = 2.
'''
fileter() 函数
filter() 函数用于过滤掉不符合条件的元素,返回一个迭代器对象。
'''
一般格式为:
filter(function, iterable)
其中,function 为判断函数, iterable 为可迭代对象
'''
# filter
def IsEvenFunc(n):
return n % 2 == 0
a = list(filter(IsEvenFunc, [1,2,3,4,5,6,7,8,9,10]))
print(a)
# [2, 4, 6, 8, 10]
zip() 函数
zip() 函数接收任意多个可迭代对象作为参数,将对象中对应的元素打包成一个元组,然后返回一个可迭代的 zip 对象。
'''
一般格式为:
zip([iterable, ... ])
其中,iterable 为一个或多个迭代器
z 仅仅是返回的可迭代对象的地址的引用(仅仅是个人理解)
'''
# 使用 zip() 函数对序列打包和解包
ls = list(zip(["泰山", "黄山", "庐山", "华山"], ["山东", "安徽", "江西", "陕西"])) # 打包
print(ls)
z = zip([1, 2, 3], [4, 5, 6]) # 打包
print("打包结果: ", list(z)) # z 仅仅是返回的可迭代对象的地址的引用
print("解包结果: ", list(zip(*z)))
'''
[('泰山', '山东'), ('黄山', '安徽'), ('庐山', '江西'), ('华山', '陕西')]
打包结果: [(1, 4), (2, 5), (3, 6)]
解包结果: [] # 此处结果不对,有待考究,使用python 命令行方式得到正确结果
'''
>>> z = zip([1,2,3],[4,5,6])
>>> list(zip(*z))
[(1, 2, 3), (4, 5, 6)]
枚举函数 enumerate()
枚举函数 enumerate() 用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标。
'''
一般格式为:
enumerate(sequence, [start = 0])
其中,
sequence:一个序列,迭代器或其他支持的迭代对象
start: 下标起始位置,可选
'''
# enumerate
weeks = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
print(list(enumerate(weeks)))
# [(0, 'Sunday'), (1, 'Monday'), (2, 'Tuesday'), (3, 'Wednesday'), (4, 'Thursday'), (5, 'Friday'), (6, 'Saturday')]
装饰器
装饰器的定义和调用
装饰器(Decorator)是 python 函数中一个比较特殊的功能,是用来包装函数的函数。装饰器可以使代码更加简洁。
装饰器常用于下列情况:
- 将多个函数中的重复代码拿出来整理成一个装饰器。对每个函数使用装饰器,从而实现代码的重用。
- 对多个函数的共同功能进行整理。例如,先单独写一个检查函数参数合法性的装饰器,然后在每个需要检查函数参数合法性的函数处调用即可。
'''
定义装饰器的一般格式为:
def decorator(func):
pass
@decorator
def func():
pass
其中:
decorator : 装饰器
@decorator : 函数的装饰器修饰符
func: 装饰器的函数对象参数
装饰器可以返回一个值,也可以返回一个函数,还可以返回一个装饰器或其他对象
'''
# 装饰器的定义和调用
# 定义装饰器
def deco(func):
print("I am in deco.")
func() # 调用函数
return "deco return value."
# 使用装饰器修饰函数
@deco
def func():
print("I am in func.")
print(func)
'''
结果为:
I am in deco.
I am in func.
deco return value.
'''
上述示例的执行原理如下:
- 装饰器 deco() 的参数为一个函数对象 func
- 函数前使用 @deco 修饰相当于将函数对象 func 作为参数调用装饰器 deco(func)。
- func 的值为调用装饰器 deco(func)的返回结果。
# 使用装饰器修改网页文本格式
# 定义装饰器
def deco(func):
# 定于函数
def modify_text(str):
return "<strong>" + func(str) + "<strong>"
return modify_text
# 使用装饰器修饰函数
@deco
def textFunc(str):
return str
print(textFunc("text"))
# <strong>text<strong>
带参数的装饰器
在调用装饰器时,除默认的参数(装饰器括号中的函数对象参数)外,还可以定义带参数的装饰器,为装饰器的定义和调用提供更多的灵活性。
# 使用带参数的装饰器检查函数参数合法性
# 定义带参数的装饰器
def DECO(args):
# 定义内部装饰器
def deco(func):
# 定义内函数
def call_func(x, y):
print("%d %s %d = " % (x, args, y), end=' ')
return func(x, y)
return call_func
return deco
# 传递装饰器参数
@DECO('&')
def andFunc(x, y): # 按位‘与’运算
return x & y
# 传递装饰器参数
@DECO('|')
def orFunc(x, y): # 按位‘或’运算
return x | y
if __name__=='__main__':
print(andFunc(5, 6))
print(orFunc(5, 6))
# 5 & 6 = 4
# 5 | 6 = 7
如果一个函数前有多个装饰器修饰,则称为多重装饰器。多重装饰器的执行顺序是:先执行后面的装饰器,再执行前面的装饰器。
变量作用域
变量类型
python 中,不同位置定义的变量决定了这个变量的访问权限和作用范围。python 中的变量可分为:
- 局部变量和局部作用域L (Local):包含在 def 关键字定义的语句块中,即在函数中定义的变量。局部变量的作用域是从函数内定义他的位置到函数结束。当函数被调用时创建一个新的局部变量,函数调用完成后,局部变量就消失了。
- 全局变量和全局作用域G(Golbal):在模块的函数外定义的变量。在模块文件顶层申明的变量具有全局作用域。从外部看,模块的全局变量就是一个模块对象的属性。全局作用域的作用范围仅限于单个模块文件内。
- 闭包变量和闭包作用域E(Enclosing):
定义在嵌套函数的外函数内、内函数外的变量。闭包变量作用域为嵌套函数内定义它的位置开始的整个函数内。 - 内建变量和内建作用域B(Built-in):系统内固定模块里定义的变量,一般预定义在内建模块内的变量。
# 变量创建位置
int(b_x) # 内建变量,位于内建函数内
g_x = 5.1 # 全局变量,位于所有函数外
def outer():
e_x = 4.8 # 闭包变量,位于外函数内、内函数外
def inner():
l_x = 6.3 # 局部变量,位于内函数内
在 python 中,当程序执行中要使用一个语句中的变量时,就会以 L(局部) —> E(闭包) —> G(全局) —> B(内建) 的规则在程序中查找这个变量的定义,即在局部范围中找不到,便会去局部范围外的局部范围(如闭包范围)中查找,若找不到就会去全局范围中查找,再去内建范围中查找。
全局变量和局部变量
- 局部变量的作用范围是从函数内定义的位置到这个函数结束。故只能在其声明的函数内访问。
- 全局变量的作用范围是整个模块内,故可以在整个模块内访问。
# 局部变量和全局变量的使用
x = 100 # 定义全局变量 x
def f(x):
print("x = ", x) # 形参 x 的值来自实参
y = 200 # 创建局部变量 y=200
print("y = ", y)
f(x) # 调用函数, 实参为全局变量 x=100
关键字 global 和 nonlocal
如果想要修改变量作用域,则需要使用关键字 global 或 nonlocal。
# global
x = 100 # 定义全局变量
def myFunc():
global x # 使用关键字 global 修改 x 为全局变量,如果没有该句,则下一句会报错
print("全局变量: x = ", x)
x = 200 # 修改全局变量
print("修改后的全局变量: x = ", x)
myFunc() # 调用函数
# 全局变量: x = 100
# 修改后的全局变量: x = 200
# nonlocal
def outerFunc():
x = 100 # 定义闭包变量 x
def innerFunc():
nonlocal x # 使用关键字nonlocal 修改 x 为闭包变量
print("闭包变量: x=", x)
x = 200 # 修改闭包变量的值
print("修改后的闭包变量: x=", x)
innerFunc()
outerFunc()
# 闭包变量: x= 100
# 修改后的闭包变量: x= 200
写在最后:
首先,如果本篇文章有任何错误,烦请读者告知!不胜感激!
其次,本篇文章仅用于日常学习以及学业复习,如需转载等操作请告知作者(我)一声!
最后,本文会持续修改和更新,如果对本分栏的其他知识也感兴趣,可以移步目录导航专栏,查看本分栏的目录结构,也更方便对于知识的系统总结!
兄弟姐妹们,点个赞呗!
感谢!笔芯!