# 变量三要素:变量名,赋值运算符,变量值
a = 10的意思是:将10这个值的内存地址指向给变量a
当我们写下a = 10这个指令时,计算机执行了以下三步操作:
1.在内存里面开辟一个名为a 的名称空间
2.在内存里面创建一个整数值10
3.将整数的内存地址指向变量a
作用域也称作用范围,也叫名称空间,按照生效范围来看可以分为全局作用域和局部作用域。
1.全局名称空间:创建的储存“变量名与值的关系”的空间叫做全局名称空间。
2.局部名称空间:在函数运行中开辟出来的空间叫做局部名称空间。
# 并非仅仅指函数,例如在模块中,在类中进行的简单赋值操作都是局部作用域
3.内置名称空间:内置名称空间中存储了python解释器为我们存储的函数,例如len(),print()等等,
都是python为我们创建好的内置函数。
# 定义在函数内部的变量拥有一个局部作用域,定义在函数外部的变量拥有全局作用域
全局作用域:包括内置命名空间和全局命名空间,在整个文件的任何文件都可以使用,遵循从上到下逐行执行的原则。
局部作用域:在函数内部可以使用
# 当内部作用域想修改外部作用域的变量时,就需要用到 global 和 nonlocal 函数了。
# 局部变量:就是在函数内部定义的变量
其作用范围时函数内部,即只能在函数中使用,在函数外是不能使用的。 因为其作用范围只是在自己的函数内部,所有不同的函数可以定义相同名字的函数变量。(打个比方,每个人都是一个函数,每个人都使用手机,我用华为,你也用华为,但是互不相干)
# 局部变量的作用:为了临时保存数据,需要在函数中定义变量再进行存储
当函数调用时,局部变量被创建,当函数调用完成后,这个变量就不能再使用了
def funa():
#局部变量的作用域(使用范围)在函数的内部 函数的外部无法使用
a = 1 # 定义一个局部变量
print('funa第一次的值:%s' % a)
a = 2
print('funa第二次的值:%s' % a)
def funb():
#在函数内部定义的局部变量名可以和其他函数中的局部变量名相同 是不冲突的
a = 3
print('funb第一次的值:%s' % a)
funa()
funb()
运行结果:
既能在一个函数中使用,也能在其他函数中使用,这就是全局变量。
# 在函数外部定义的变量是全局变量
# 全局变量能够在所有的函数中进行访问
li = []
for i in range(5):
li.append(i)
print(li)
print(li)
运行结果:
a =100
def funa():
函数内部如果使用一个变量,会先从函数内部找,如果有直接使用;
如果函数内部没有找到,会到函数外面找(全局变量),没找到就报错
print(a)
def funb():
print(a)
funa()
funb()
运行结果:
# 全局变量和局部变量名字相同问题
a =100
def funa():
a = 200 定义了一个和全局变量名相同的局部变量
print(a)
def funb():
print(a)
funa()
funb()
运行结果:
当函数内出现局部变量和全局变量名字相同时,可以理解为“变量名 = 数据” 定义了一个局部变量,而不是修改全局变量。
# 全局变量和局部变量名字相同问题
a =100
def funa():
a = 200 定义了一个和全局变量名相同的局部变量
print(a)
def funb():
print(a)
funa()
funb()
运行结果:
局部作用域对全局作用域的变量(此变量只能是不可变的数据类型)只能进行引用,不能修改,只要改变就会报错,但有些时候,我们会遇到让局部变量改变全局变量的一些数据的需求,这又该怎么办呢?这就需要用到python 的关键字 global 。
a = 1
def funa():
a = 2 # 声明了一个局部变量,与外面等于1的那个a没有关系了
print(a)
funa()
print(a)
运行结果:
使用global后:
def funa():
标识函数内部不是定义一个局部变量,其实是对全局的修改
global a # 全局的a变成了由1变成了2
a = 2
print(a)
funa()
print(a)
运行结果:
a = 1
def fun():
print(a) # 先引用
a = 2 # 再修改
fun()
print(a)
# 在内部函数修改同名全局变量之前调用变量名称,则引发Unbound-LocalError
运行结果:
a = 1
def fun():
global a # a为全局变量
print(a)
a = 2 # 改变的是全局变量,因此出了这个局部作用域,仍然有效
fun()
print(a)
运行结果:
def funa():
global a
a = 2
print(a)
funa() # 2
print(a) # 函数外没有定义a,但是还是会打印出a的值为2
运行结果:
总结一下:
所以global关键字一共有两个作用:
如果函数中出现 global 全局变量的名字,那么这个函数中即使出现和全局变量一样名字的“变量名 = 数据”,也理解为对全局变量进行修改,而不是定义局部变量。
如果一个函数中需要对多个全局变量进行修改,那么可以使用
# 可以使用一次global对多个全局变量进行声明
global a, b
# 还可以用多次global声明都是可以的
# global a
# global b
a = 1
b = 2
def funa():
global a, b
a = 2
b = 3
print(a, b)
print(a, b) # 1 2
funa() # 2 3
print(a, b) # 2 3
运行结果:
nonlocal是python3x新加的功能,与global用法差不多,就是在局部作用域如果想对父级作用域的变量进行改变时,需 要用到nonlocal,当然这个用的不是很多,了解即可。
nonlocal只能在封装函数中使用,在外部函数先进行声明,在内部函数进行nonlocal声明。
nonlocal 总结:
# nonlocal 关键字只能用于嵌套函数中
nonlocal 声明的变量只对局部起作用,离开封装函数,那么该变量就无效。
错误用法:在外部函数中声明nonlocal,外部函数中变量声明用globa。
举个例子:
a = 10
def funa():
a = 1
def funb():
nonlocal a # a为外层变量
print('funb函数中a的值:', a)
a = 2
funb()
print('funa函数中a的值:', a)
funa()
print(a)
运行结果:
错误用法:
a = 1
def funa():
global a
a = 2
def funb():
nonlocal a
print(a)
a = 3
funb()
print(a)
funa()
print(a)
运行结果:
原因分析:当使用 nonlocal 声明变量 a 时,就会往上最近一层局部作用域寻找局部变量 a ,此时外层局部作用域虽然能找到变量 a ,但是找到的这个变量 a 已经被 global 声明为全局变量了,所以会报错。
(1)两者的功能不同。
global 关键字修饰变量后,该变量为全局变量,对该变量进行修改就是在修改全局变量,而nonlocal 关键字修饰变量后,该变量为上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal 位置会发生错误,因此,最上层的函数使用nonlocal 关键字修饰变量一定会报错。
(2)两者的使用范围不同
global 关键字可以使用在任何地方,包括最上层函数和嵌套函数,即使之前未定义该变量,经global 关键字修饰后仍然可以使用,不会报错,而nonlocal 关键字只能使用在嵌套函数中,并且外层函数中含有被声明的局部变量,否则会发生错误。(可以参照举的例子)
(3)global 关键字可以将局部变量变为全局变量,nonlocal 关键字可以在内层函数中修改外层函数(非全局)变量。
匿名函数,顾名思义就是没有名字的函数,那么什么函数没有名字呢?这个就是我们以后会经常用到的 lambda ,这就是匿名函数,也叫一句话函数。
使用匿名函数有个好处,因为函数没有名字,所以不用担心函数名冲突。
此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用匿名函数。
# 匿名函数语法:
函数名 = lambda 参数:返回值
举个例子:
# 函数求和:
def func(a,b):
return a+b
print(func(1,2))
# 匿名函数:
funa = lambda a,b:a+b # a,b就是他们的参数(形参) a+b是返回值
# 匿名函数不需要return来返回值,表达式本身结果就是返回值
print(funa(3,4))
运行结果:
在字符串中,返回索引为0和2的元素(列表形式)
方法1:
str1 = 'abcde'
a = []
a.append(str1[0])
a.append(str1[2])
print(a)
运行结果:
方法二:
str1 = 'abcde'
li = list(str1[0:3])
li.remove('b')
print(li)
运行结果同上
方法三:
func = lambda x: [x[0], x[2]]
print(func('abcde'))
运行结果同上
对比一下,是不是 lambda 关键字更方便一些。
if - else 的使用:
#三目运算:
a = 4
b = 3
print(a) if a > b else print(b)
#匿名函数:
func = lambda x,y: x if x > y else y
print(func(3,100))
# 嵌套if else
we = lambda a, b: a if a > b else b
print(we(4, 5))
# 平方值
a = lambda x: x**2
print(a(10)) # 100
运行结果:
三目运算可以省时省力,具体可以参照以前的文章 (个人复习计划第四篇)。
# 查看所有的内置函数
import builtins
print(dir(builtins))
# 大写字母开头的是python的内置常量名,小写字母开头的是python的内置函数名。
运行结果:
'ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError',
'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError',
'ConnectionError'
有点多,我没有列举完,可以根据代码自行查看。
举例1:
# 1.list() 将一个可迭代对象转换成列表
a = 'abc'
print(a)
print(list(a))
运行结果:
举例2:
# 2.tuple() 将一个可迭代对象转换成元组
a = 'abc'
print(a)
print(tuple(a))
运行结果:
举例3:
# 3.abs() 返回绝对值
print(abs(-3)) # 3
运行结果:
举例4:
# 4.sum() 求和
print(sum([1, 2, 3]))
运行结果:
举例5:
# 5.min() 求最小值
print(min([1, 2, 3]))
运行结果:
reversed() 将一个序列翻转, 返回翻转序列的迭代器
bytes() 把字符串转换成bytes类型
举例6:
# 6.set()创建一个无序不重复元素集
li = [1, 2, 3]
s1 = set(li)
print(s1)
运行结果:
zip()拉链函数:
zip()拉链方法。该方法用于将可迭代的对象作为参数,将对象中相对应的参数组成一个个元组,然后返回由这些元组组成的内容,如果迭代器的元素个数不一致,则按长度最短的返回。
# 其中zip()函数就是将几个数组对齐,然后按列输出。
举例1:
a = [1, 2, 3]
b = ['a', 'b', 'c']
print(list(zip(a, b)))
运行结果:
举例2:
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)
运行结果:
map()映射函数:
map(function,iterable)映射函数
可以对可迭代对象中的每一个元素进行映射,分别取出执行function
把函数依次作用在list中的每一个元素上,再得到一个新的list并返回
举例:
# 计算列表中每个元素的平方,返回新列表
li = [1, 2, 3, 4]
def funa(x):
return x*x
mp = map(funa,li )
print(list(mp))
运行结果:
换种方法:
lambda函数:
a = [1, 2, 3, 4,]
print(list(map(lambda s:s*s, a)))
运行结果同上
reduce()函数:对参数序列中元素进行累积
reduce(函数名,可迭代对象)# 这两个参数必须都要有,缺一个都不行。
# 拓展:在python2.x版本中,直接通过import 导入,python3.x中需要从functools 这个包中导入。
它的作用是把列表中前两个数据取出计算出一个值然后临时保存着,接下来用这个临时值与第三个值进行计算,得到一个新的临时值,并且把初始的临时值覆盖掉,接下来仍旧重复此操作,这就是累积的思想。
举个例子:
from functools import reduce
def func(x, y):
return x + y
res = reduce(func, [1,2,3,4])
print(res) # 运行结果:10
l = reduce(lambda x, y: x+y, [1, 2, 3, 4])
print(l) # 运行结果:10
运行结果:
filter()
filter()函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件的元素组成的新列表。
接收两个参数,第一个为函数,第二个为序列,序列中的每个元素作为参数传递给函数进行判断,然后返回True或False,最后将返回True的元素放到新列表中。
举个例子:
li = [2, 3, 5, 7, 10]
def funa(x):
return x > 5
print(list(filter(funa, li))) # 过滤函数,过滤条件 filter过滤
运行结果:
eval()函数用来执行一个字符串表达式,并返回表达式的值。
eval ( expression [ , global [ , locals]] )
a = '[1, 2, 3]'
# a = '(1, 2, 3)'
# a = "{'a':'zs', 'b':12}"
# a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
b = eval(a)
print(b)
print(type(b))
运行结果:
2.将 string 转化为算术表达式执行
print(eval('1+2')) # 3
a = 1
b = 2
print(eval('a+b')) # 3
运行结果:
enumerate()--- 枚举
enumerate()函数用于将一个可遍历的数据对象(如列表,字典,元组等等)组合成一个索引序列,同上列出数据和数据下标,通常用于 for 循环中。
语法:enumerate(sequence,[ start = 0])
sequence ---- 一个序列,迭代器或其他支持迭代对象
举例1:
li = ['a', 'b', 'c', 'd']
for i, j in enumerate(li):
print(i, j)
运行结果:
举例2:
li = ['a', 'b', 'c', 'd']
print(list(enumerate(li)))
print(dict(enumerate(li)))
运行结果:
来做个题练练手:
题目:在python3中,编写函数,实现接收一个字符串,分别统计大写字母、小写字母、数字、 其他字符的个数,并以元组的形式返回结果(利用函数,判断,循环实现)。
分析:
1.定义一个函数
2. 在函数里面定义4个变量,分别表示大写字母,小写字母,数字,其它字符的个数
3. for循环遍历字符串
4. if语句判断变量的到字符是大写字母、小写字母、数字、还是其他字符
5. 根据判断的结果,让对应的变量加1
6. 循环结束,返回这4个变量组成的元组
参考答案:
# 1.定义一个函数funa(st)
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 = []
def funa(a):
# a = "h2LLo w34rld"
i = 0
while i < len(a):
if a[i].islower():
# print('小写:', a[i])
a1.append(a[i])
elif a[i].isupper():
# print('大写:', a[i])
b1.append(a[i])
elif a[i].isdigit():
# print('数字:', a[i])
c1.append(a[i])
i += 1
funa('ab123WQ')
print(len(a1))
print(len(b1))
print(len(c1))
运行结果:
欧耶,函数部分的知识点(除了拆包) 我都已经复习完了,最近是期末周,但是影响不了我的蓝桥杯复习,接下来就是做题+复习知识点。这篇就这样吧,下次继续!