python 函数详细笔记


函数定义和调用


函数定义

  • 函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码段。
  • 使用函数能提高应用的模块性、代码的重用率和可读性。
'''
用户自定义函数的一般格式为:
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.
'''

函数调用

  • 函数调用时需要指出函数名称,并传入相应的参数。
  • 函数调用时传入的参数称为实际参数(即实参)。
  • 默认情况下,函数调用时传入的实参个数、顺序等必须和函数定义时形参的个数、顺序一致。

函数调用时的执行顺序如下:

  1. 执行函数调用前的语句
  2. 执行函数调用,运行被调用函数内的语句,并返回相应结果
  3. 执行函数调用后的语句
# 求一个梯形的面积
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() 函数有如下区别:

  1. type() 不会认为子类对象是一种父类类型,不考虑继承关系。
  2. 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.
'''

上述示例的执行原理如下:

  1. 装饰器 deco() 的参数为一个函数对象 func
  2. 函数前使用 @deco 修饰相当于将函数对象 func 作为参数调用装饰器 deco(func)。
  3. 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

写在最后:
首先,如果本篇文章有任何错误,烦请读者告知!不胜感激!
其次,本篇文章仅用于日常学习以及学业复习,如需转载等操作请告知作者(我)一声!
最后,本文会持续修改和更新,如果对本分栏的其他知识也感兴趣,可以移步目录导航专栏,查看本分栏的目录结构,也更方便对于知识的系统总结!
兄弟姐妹们,点个赞呗!
感谢!笔芯!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值