目录
一、名称空间(Namespace)
是一个存储变量和函数名称的容器,用于在程序中对标识符(例如变量名、函数名)进行组织和管理。它使得不同部分的代码可以具有相同名称的标识符,而不会引起冲突。
1、内置名称空间(Built-in Namespace)
包含了 Python 解释器中预定义的函数、变量和异常名称。这些名称在任何 Python 程序中都是可用的,无需导入。
2、全局名称空间(Global Namespace)
是在模块级别定义的名称空间,它包含了在整个模块中定义的变量、函数等标识符。这些标识符可以在整个模块中访问。
3、局部名称空间(Local Namespace)
是在函数内部定义的名称空间,它包含了在函数内部定义的变量、函数等标识符。这些标识符只在函数内部可见。
4、嵌套名称空间(Enclosing Namespace)
发生在嵌套的函数内部,它包含了在外部函数中定义的变量、函数等标识符。内部函数可以访问外部函数的名称空间,但外部函数不能访问内部函数的名称空间。
名称空间通过层次结构组织起来,形成了名称解析的规则。当引用一个标识符时,Python 解释器会根据从内到外的顺序搜索相应的名称空间,找到第一个匹配的标识符。
这些名称空间和层次结构共同构成了 Python 的变量查找和访问机制。
二、作用域(Scope)
作用域是指在程序中定义变量的区域,它决定了在何处可以访问或引用变量。
1、内置作用域(Built-in Scope)
是 Python 中预定义的变量和函数的作用域,例如内置的函数和异常名称。
result = sum([1, 2, 3]) # sum 是内置函数,可以在任何地方访问
try:
x = 1 / 0 # 除以零会引发内置异常 ZeroDivisionError
except ZeroDivisionError as e:
print(e) # 可以访问内置异常 ZeroDivisionError
2、全局作用域(Global Scope)
是在模块(文件)级别定义的变量的作用域。这些变量可以在整个模块中访问。
z = 15 # z 在模块顶层定义,是全局变量
def another_function():
print(z) # 可以在函数内部访问全局变量 z
another_function()
print(z) # 可以在模块顶层访问全局变量 z
3、局部作用域(Local Scope)
是在函数内部定义的变量的作用域。这些变量只能在函数内部访问,函数外部无法直接访问这些变量。
def my_function():
x = 10 # x 在函数内部定义,是局部变量
print(x) # 可以在函数内部访问 x
my_function()
# print(x) # 这里会报错,x 在函数外部无法访问
4、嵌套作用域(Enclosing Scope)
发生在函数内部嵌套的函数中。内部函数可以访问外部函数的变量,但是外部函数不能访问内部函数的变量。
def outer_function():
y = 5 # y 在外部函数定义
def inner_function():
print(y) # 内部函数可以访问外部函数的变量 y
inner_function()
outer_function()
# print(y) # 这里会报错,y 在内部函数外部无法访问
三、全局变量和局部变量
1、全局变量
(1)定义
在模块的顶层(即没有嵌套在其它结构内部)定义的变量,既能在一个函数中使用,也能在其它的函数中使用,可以在模块内部的任何地方访问和修改这些变量。
(2)作用范围
在函数外边定义的变量叫做全局变量,可以在任何位置使用。
(3)作用
全局变量能够在所有的函数中进行访问。
# 例一:
a = 100
def funa():
# 函数内部如果使用一个变量,会先从函数内部找,如果有直接使用;
# 如果函数内部没有找到,会到函数外面找(全局变量),没找到就报错
print(a) # 100
def funb():
print(a) # 100
funa()
funb()
# 运行结果:
# 100
# 100
# 例二:
a = 100
def funa():
a = 200 # 定义了一个和全局变量名相同的局部变量
print(a) # 200
def funb():
print(a) # 100
funa()
funb()
# 运行结果:
# 200
# 100
当函数内出现局部变量和全局变量相同名字时,函数内部中的
变量名 = 数据
此时理解为定义了一个局部变量,而不是修改全局变量的值。
2、局部变量
(1)定义
是在函数内部通过赋值语句定义的变量。这些变量只在包含它们的函数内部可见和可用。
(2)作用范围
这个函数内部,即只能在这个函数中使用,在函数的外部是不能使用的,它在函数内部创建,在函数调用结束后被销毁。
因为其作用范围只是在自己的函数内部,所以不同的函数可以定义相同名字的局部变量。
(3)作用
为了临时保存数据需要在函数中定义变量来进行存储,当函数调用时,局部变量被创建,当函数调用完成后,这个变量就不能够使用了。
def funa():
# 局部变量的作用域(使用范围)在函数的内部,函数的外部无法使用
a = 1 # 定义一个局部变量
print('funa第一次的值:%s' % a) # funa第一次的值:1
a = 2
print('funa第二次的值:%s' % a) # funa第二次的值:2
def funb():
#在函数内部定义的局部变量名可以和其他函数中的局部变量名相同,是不冲突的
a = 3
print('funb第一次的值:%s' % a) # funb第一次的值:3
funa()
funb()
# 运行结果:
# funa第一次的值:1
# funa第二次的值:2
# funb第一次的值:3
3、修改全局变量 global
局部作用域对全局作用域的变量(此变量只能是不可变的数据类型)只能进行引用,而不能进行改变,只要改变就会报错。-
但是有些时候,在程序中会遇到局部作用域去改变全局作用域的一些变量的需求,这就得用到关键字 global。
(1)作用1
在局部作用域中可以更改全局作用域的变量,声明一个全局变量。
# 例一:
a = 1
def funa():
a = 2 # 声明了一个局部变量,与外面等于1的那个 a 没有关系了
print(a) # 2
funa()
print(a) # 1
# 运行结果:
# 2
# 1
def funa():
# 标识函数内部不是定义一个局部变量,其实是对全局的修改
global a # 全局的 a 变成了由1变成了2
a = 2
print(a) # 2
funa()
print(a) # 2
# 运行结果:
# 2
# 2
# 例二:
# 在内部函数修改同名全局变量之前调用变量名称,则引发 Unbound-LocalError
a = 1
def fun():
print(a) # 先引用
a = 2 # 再修改
fun()
print(a)
# 运行结果:
# UnboundLocalError: local variable'a' referenced before assignment
# python 认为 a 不一定能被赋值。
# 例三:
a = 1
def fun():
global a # a 为全局变量
print(a) # 1
a = 2 # 改变的是全局变量,因此出了这个局部作用域,仍然有效
fun()
print(a) # 2
# 运行结果:
# 1
# 2
(2)作用2
在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)。
def funa():
global a
a = 2
print(a) # 2
funa()
# 函数外没有定义 a,但是还是会打印出 a 的值为2
print(a) # 2
# 运行结果:
# 2
# 2
如果在函数中出现 global 全局变量的名字,那么这个函数中即使出现和全局变量名相同的 变量名 = 数据
,也理解为对全局变量进行修改,而不是定义局部变量。-
如果在一个函数中需要对多个全局变量进行修改,那么可以使用一次 global 对多个全局变量进行声明,也可以用多次 global 声明。
a = 1
b = 2
def funa():
# 使用一次 global 对多个全局变量进行声明
global a, b
# 也可以用多次 global 声明
# global a
# global b
a = 2
b = 3
print(a, b) # 1 2
print(a, b) # 2 3
funa()
print(a, b) # 2 3
# 运行结果:
# 1 2
# 2 3
# 2 3
4、声明外层的局部变量 nonlocal
是 python3x 新加的功能,只能在封装函数中使用,在外部函数先进行声明,在内部函数进行 nonlocal 声明。
-
不能更改全局变量。
-
在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下,此变量全部发生改变。
-
只对局部起作用,离开封装函数,那么该变量就无效。
a = 10
def funa():
a = 1
def funb():
nonlocal a # a 为外层变量
print(‘funb函数中a的值:’, a) # funb函数中a的值: 1
a = 2
funb()
print(‘funa函数中a的值:’, a) # funa函数中a的值: 2funa()
print(a) # 10运行结果:
funb函数中a的值: 1
funa函数中a的值: 2
10
错误用法:在外部函数进行声明 nonlocal; 外部函数中变量声明为 global。
# 错误使用
a = 1
def funa():
global a
a = 2
def funb():
nonlocal a
print(a)
a = 3
funb()
print(a)
funa()
print(a)
# 运行结果:
# SyntaxError: no binding for nonlocal 'a' found
原因分析:-
当使用 nonlocal 声明变量 a 时,就会往上最近一层局部作用域寻找局部变量 a,-
此时外层局部作用域虽然能找到变量 a,但是这找到的这个 a 已经被 global 声明为全局变量了,-
nonlocal 不能改变全局变量,所以报错。
5、global 和 nonlocal 的区别
1、功能不同。
global 关键字修饰变量后,标识该变量是全局变量,对该变量进行修改就是修改全局变量。
nonlocal 关键字修饰变量后,标识该变量是上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal 位置会发生错误(最上层的函数使用 nonlocal 修饰变量必定会报错)。
2、使用的范围不同。
global 关键字可以用在任何地方,包括最上层函数中和嵌套函数中,即使之前未定义该变量,global 修饰后也可以直接使用。
nonlocal 关键字只能用于嵌套函数中,并且外层函数中定义了相应的局部变量,否则会发生错误。
3、作用对象不同。
global 关键字可以将局部变量变成一个全局变量。
nonlocal 关键字可以在内函数中修改外层(非全局)变量。
四、匿名函数
就是没有名字的函数,匿名函数 lambda,也叫一句话函数。
因为函数没有名字,不必担心函数名冲突。通常情况下,这样的函数只使用一次。
匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数。
语法:
函数名 = lambda 参数:返回值
1)此函数也可以有名字,它的名字就是给其设置的变量,比如 funa。
2)lambda 是定义匿名函数的关键字,相当于函数的 def。
3)lambda 后面直接加形参,形参加多少都可以,只要用逗号隔开就行。
案例:
1、求和
# 函数求和:
def func(a,b):
return a + b
print(func(1,2)) # 3
# 匿名函数求和:
funa = lambda a,b:a+b # a,b 就是它们的参数(形参),a+b 是返回值
# 匿名函数不需要 return 来返回值,表达式本身结果就是返回值
print(funa(1,2)) # 3
2、在字符串中,返回索引为0跟2的对应的元素(列表形式)
str1 = 'abcde'
# 方法一:
a = []
a.append(str1[0])
a.append(str1[2])
print(a) # ['a','c']
# 方法二:
li = list(str1[0:3])
li.remove('b')
print(li) # ['a','c']
# 方法三:
func = lambda x: [x[0], x[2]]
print(func('abcde')) # ['a','c']
3、接收两个 int 参数,将较大的数据返回
a = 4
b = 3
# 三目运算
print(a) if a > b else print(b) # 4
# 匿名函数
func = lambda x,y: x if x > y else y
print(func(4,3)) # 4
# 嵌套 if else
we = lambda a,b: a if a > b else b
print(we(4, 3)) # 4
4、求平方值
a = lambda x: x**2
print(a(10)) # 100
5、在 sorted 函数中使用匿名函数,对列表中的元组按第二个元素排序
data = [(2, 5), (1, 9), (4, 3)]
sorted_data = sorted(data, key=lambda x: x[1])
print(sorted_data) # [(4, 3), (2, 5), (1, 9)]
五、内置函数
是 Python 解释器内置的一组函数,它们无需导入模块即可在任何地方直接使用。
内置函数提供了各种功能,从基本的数学运算到字符串处理、列表操作、文件操作等,是直接可以拿来使用的函数。
# 查看所有的内置函数
import builtins
print(dir(builtins))
# 大写字母开头的是 python 的内置常量名,
# 小写字母开头的是 python 的内置函数名。
列举常用的内置函数:
1、数学函数
- abs(x): 返回 x 的绝对值。
- round(x, n): 返回 x 的四舍五入值,n 为小数点后保留的位数。
2、类型转换函数
- int(x): 将 x 转换为整数。
- float(x): 将 x 转换为浮点数。
- str(x): 将 x 转换为字符串。
3、序列操作函数
- len(seq): 返回序列 seq 的长度。
- sorted(iterable): 返回一个排序后的列表,可用于各种可迭代对象。
- max(iterable) 和 min(iterable): 返回可迭代对象中的最大和最小值。
4、字符串处理函数
- len(s): 返回字符串 s 的长度。
- str.capitalize(): 返回字符串的副本,首字母大写。
- str.upper() 和 str.lower(): 返回字符串的大写和小写版本。
5、列表操作函数
- list.append(x): 将元素 x 添加到列表末尾。
- list.extend(iterable): 将可迭代对象的元素添加到列表末尾。
- list.pop(index): 删除并返回指定位置的元素。
6、字典操作函数
- dict.keys(), dict.values(), dict.items(): 返回字典的键、值、键值对视图。
- dict.get(key, default): 返回键 key 对应的值,如果不存在则返回默认值 default。
7、文件操作函数
- open(file, mode): 打开文件并返回文件对象,用于读写文件。
- file.read(), file.readline(), file.readlines(): 读取文件内容。
- file.write(text): 将文本写入文件。
8、其他函数
- print(): 打印输出到控制台。
- input(prompt): 从用户获取输入。
案例:-
1、zip()
拉链函数,用于将多个可迭代对象(如列表、元组等)按元素顺序进行配对,生成一个新的迭代器。这个迭代器生成的元素是一个个元组,每个元组包含来自各个输入可迭代对象的对应位置的元素。
常见用途是将多个列表按索引位置进行组合,从而便于同时迭代多个列表的元素。
# 例一:
a = [1, 2, 3]
b = ['a','b','c']
print(list(zip(a, b)))
# 运行结果:
# [(1,'a'), (2,'b'), (3,'c')]
# 例二:
a = [1, 2, 3]
b = ['a','b','c','d']
c = (6, 5, 4, 3, 2, 1)
for i in zip(a, b, c):
print(i)
# 运行结果:
# (1, 'a', 6)
# (2, 'b', 5)
# (3, 'c', 4)
注意:
- 当输入的可迭代对象长度不一致时,zip() 函数会按最短的可迭代对象的长度来组合元素。
- 如果需要获取完整的组合元素,可以使用 list() 函数将迭代器转换为列表。
2、map()
映射函数,可以对可迭代对象中的每一个元素进映射,分别去执行 function 把函数依次作用在 list 中的每一个元素上,得到一个新的 list 并返回。
这个函数在需要对一个序列中的每个元素执行相同操作时非常有用。
# 计算列表中每个元素的平方,返回新列表
li = [1, 2, 3, 4]
def funa(x):
return x*x
mp = map(funa,li )
print(list(mp))
# 运行结果:
# [1, 4, 9, 16]
# lambda 函数:
a = [1, 2, 3, 4,]
print(list(map(lambda s:s*s, a)))
# 运行结果:
# [1, 4, 9, 16]
注意:
- map() 函数会将传入的函数应用于每个可迭代对象对应位置的元素。如果输入的可迭代对象长度不一致,map() 函数会按最短的可迭代对象的长度来生成结果。
- 如果需要获取完整的结果列表,可以使用 list() 函数将迭代器转换为列表。
3、filter()
用于过滤序列,过滤掉不符合条件的元素, 返回由符合条件元素组成的新列表。
接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
# 筛选出列表中的偶数元素
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
def is_even(x):
return x % 2 == 0
even_numbers = filter(is_even, numbers)
print(list(even_numbers))
# 运行结果:
# [2, 4, 6, 8]
# lambda 函数:
numbers = [1, 2, 3, 4, 5]
filtered_numbers = filter(lambda x: x > 2, numbers)
print(list(filtered_numbers))
# 运行结果:
# [3, 4, 5]
注意:
- filter() 函数将可迭代对象中的元素依次应用 function 函数,并保留返回值为 True 的元素。如果 function 函数未提供,filter() 函数会默认保留为真值的元素。
- 如果需要获取完整的筛选结果列表,可以使用 list() 函数将迭代器转换为列表。
4、enumerate()
用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
li = ['a','b','c','d']
for i, j in enumerate(li):
print(i, j)
print(list(enumerate(li))) # [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
print(dict(enumerate(li))) # [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
# 运行结果:
# 0 a
# 1 b
# 2 c
# 3 d
# [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]
# {0: 'a', 1: 'b', 2: 'c', 3: 'd'}
注意:
- 默认情况下,enumerate() 函数从索引 0 开始对元素进行编号。可以通过设置 start 参数来指定起始索引。
- enumerate() 返回的枚举对象可以使用 list() 函数转换为列表,或用于其它迭代操作。
5、eval()
用来执行一个字符串表达式,并返回表达式的值。
# 1、可以把 list、tuple、dict 和 string 相互转化。
a = '[1, 2, 3]'
a1 = eval(a)
print(a1) # [1, 2, 3]
print(type(a1)) # <class 'list'>
b = '(1, 2, 3)'
b1 = eval(b)
print(b1) # (1, 2, 3)
print(type(b1)) # <class 'tuple'>
c = "{'a':'zs','b':12}"
c1 = eval(c)
print(c1) # {'a': 'zs', 'b': 12}
print(type(c1)) # <class 'dict'>
d = "([1,2], [3,4], [5,6], [7,8], (9,0))"
d1 = eval(d)
print(d1) # ([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))
print(type(d1)) # <class 'tuple'>
# 2、将 string 变成算术表达式来执行
print(eval('1+2')) # 3
a = 1
b = 2
print(eval('a+b')) # 3
六、应用
1、名片管理器
print('名片管理系统')
print('1、添加名片')
print('2、删除名片')
print('3、修改名片')
print('4、获取名片')
print('5、退出系统')
Ncard = ['a','b','c']
# 获取选择
def choice():
inp = int(input('请输入你要进行的操作:'))
return inp
# 添加
def add():
newcard = input('请输入姓名:')
Ncard.append(newcard)
# 删除
def rem():
delcard = input('请输入姓名:')
Ncard.remove(delcard)
# 修改
def upd():
name = input('请输入原名:')
index = Ncard.index(name)
newname = input('请输入修改后的名字:')
Ncard[index] = newname
# 获取
def get():
print(Ncard)
i = 0
while i < 2:
key = choice()
if key == 1:
add()
elif key == 2:
rem()
elif key == 3:
upd()
elif key == 4:
get()
elif key == 5:
print('感谢您的使用,欢迎下次再来')
break
else:
print('输入有误,请重新输入')
2、编写函数,实现接收一个字符串,分别统计大写字母、小写字母、数字、 其它字符的个数,并以元组的形式返回结果(利用函数,判断,循环实现)。
分析:
1、定义一个函数
2、在函数里面定义4个变量,分别表示大写字母,小写 字母,数字,其它字符的个数
3、for循环遍历字符串
4、if语句判断变量的到字符是大写字母、小写字母、 数字、还是其他字符
5、根据判断的结果,让对应的变量加1
6、循环结束,返回这4个变量组成的元组
# 1.定义一个函数 funa()
def funa(st):
# 2. 在函数里面定义4个变量,分别表示大写字母、小写字母、数字、其它字符的个数
up = 0
lo = 0
nu = 0
oh = 0
# 3. for 循环遍历字符串
for i in st:
# 4. if 语句判断变量的到字符是大写字母、小写字母、数字、还是其它字符
if i.isupper(): # isupper() 方法检测字符串中所有的字母是否都为大写。
# 5. 根据判断的结果,让对应的变量加1
up += 1
elif i.islower(): # islower() 方法检测字符串是否由小写字母组成。
# 5. 根据判断的结果,让对应的变量加1
lo += 1
elif i.isdigit(): # isdigit() 方法检测字符串是否只由数字组成。
# 5. 根据判断的结果,让对应的变量加1
nu += 1
else:
# 5. 根据判断的结果,让对应的变量加1
oh += 1
print(up, lo, nu, oh)
funa('ab QW123')
# while 循环实现
a1 = []
b1 = []
c1 = []
d1 = []
def funa(a):
i = 0
while i < len(a):
if a[i].isupper():
# 大写
b1.append(a[i])
elif a[i].islower():
# 小写
a1.append(a[i])
elif a[i].isdigit():
# 数字
c1.append(a[i])
else:
# 其它
d1.append(a[i])
i += 1
funa('ab QW123')
print(len(a1),len(b1),len(c1),len(d1))