一、global和nonlocal
1.global
# global:全局
# 1.a表示两个不同的变量
a = 15 # 全局作用域
def check():
a = 88 # 局部作用域
print(a) # 88
check()
print(a) # 15
print("*" * 50)
# b.a表示两个不同的变量
a = 15
def check():
a = 20
a += 88 # a = a + 88
print(a) # 108
check()
print(a) # 15
print("*" * 50)
# c.a表示相同的变量
a = 15
def check():
# UnboundLocalError: local variable 'a' referenced before assignment
global a # 声明a来自于全局变量
a += 88 # a = a + 88
print(a) # 103
check()
print(a) # 103
"""
注意:
1.默认情况下,如果不同作用域内的变量重名,在可以访问的权限内,按照就近原则访问
2.如果全局作用域和局部作用域内的变量重名,如果需要在函数内部使用全局变量参与运算,则可以通过global进行声明
"""
"""
# 面试题
a = 15
def check():
a += 88
print(a)
check()
print(a) 103
"""
2.nonlocal
# nonlocal:不是局部
# 说明:nonlocal一般使用在函数的嵌套定义 或者 闭包中
# 1.
def outer1():
name = "abc"
def inner1():
# UnboundLocalError: local variable 'name' referenced before assignment
nonlocal name # 声明name不是局部的,是函数作用域内的变量
name += 'hello' # name = name + 'hello'
print(name) # abchello
print(name) # abc
inner1()
print(name) # abchello
outer1()
# 2.
# a.
x = 1
def outter2():
x = 2
def inner2():
x = 3 # 定义新的变量
print("内部:",x)
print("外部:",x)
inner2()
outter2()
print("全局:",x)
"""
外部: 2
内部: 3
全局: 1
"""
x = 1
def outter2():
x = 2
def inner2():
nonlocal x
x = 3 # 表示给x = 2中的x重新赋值
print("内部:",x) # 3
inner2()
print("外部:", x) # 2--》3
outter2()
print("全局:",x)
"""
内部: 3
外部: 2--->3
全局: 1
"""
"""
注意:
1.默认情况下,如果不同作用域内的变量重名,在可以访问的权限内,按照就近原则访问
2.在函数嵌套定义的情况下,如果函数作用域和局部作用域内的变量重名,
如果需要在内部函数中使用函数作用域内的变量,则可以通过nonlocal进行声明
"""
# 【面试题】简述global和nonlocal关键字的使用,举例说明
二、生成器
# 1,概念
"""
问题:
列表:一次性将所有的元素全部定义出来,如果只需要访问其中的前几个元素,大量的内存空间会被浪费
解决方案:
使用第n个元素,则只需要生成前n元素,在Python中,将这种一边使用,一般计算的机制被称为生成器(generator)
生成器的定义方式有两种:
a.将列表推导式中的[]改为()
b.函数结合yield,定义函数生成器
"""
# 1.方式一
# 列表推导式
list1 = [i for i in range(10000)]
print(type(list1)) #<class 'list'>
print(list1)
# 生成器
ge1 = (i for i in range(10000))
print(type(ge1))
print(ge1)
# 2.访问生成器中的元素
# a.next(生成器)获取生成器中的下一个元素
ge1 = (i for i in range(5))
# print(next(ge1))
# print(next(ge1))
# print(next(ge1))
# print(next(ge1))
# print(next(ge1))
# 注意:定义一个生成器,通过next()获取生成器中的下一个元素,当所有元素全部生成获取完毕,再次next(),则报错StopIteration
# print(next(ge1))
# b.for循环
# for n in ge1:
# print(n)
# 3.方式二
# a
def test1():
return 10
r1 = test1()
print(r1,type(r1)) # 10 <class 'int'>
# b
# 只要在函数内部出现yield关键字,则该函数就是一个函数生成器,yield关键字后面的数据将是生成器中的元素
def test1():
yield 10
r1 = test1()
print(r1,type(r1)) # <generator object test1 at 0x0000021523610570> <class 'generator'>
# print(next(r1))
for n in r1:
print(n)
# c.
def test2():
yield 10
yield 20
yield 30
r2 = test2()
for n in r2:
print(n)
# d.
# 获取一个生成器中的3个元素
def test3(n):
for i in range(n):
yield i ** 2
r3 = test3(5)
print(next(r3)) # 0
print(next(r3)) # 1
print(next(r3)) # 4
# 分别获取三个生成器中的第0个元素
def test3(n):
for i in range(n):
yield i ** 2
print(next(test3(5)))
print(next(test3(5)))
print(next(test3(5)))
# 注意:在函数生成器中,只要函数调用一次,则表示生成一个新的生成器
三、可迭代对象和迭代器
"""
【面试题】简述可迭代对象和迭代器之间的区别和联系
区别:
可迭代对象:Iterable,可以直接作用于for循环的对象【可以使用for循环遍历其中元素的对象】,
如:list,tuple,dict,set,str,range(),生成器等
迭代器:Iterator,可以直接作用于for循环,或者可以通过next()获取下一个元素的对象,
如:生成器
联系:
迭代器一定是可迭代对象,可迭代对象不一定是迭代器
但是,可以通过系统功能iter()将不是迭代器的可迭代对象转换为迭代器
"""
# isintance(变量,类型):判断一个变量的类型是否是指定的类型
from collections import Iterable,Iterator
# 1.
print(isinstance([34],Iterable)) # True
print(isinstance((34,),Iterable))
print(isinstance("agag",Iterable))
print(isinstance({"a":10},Iterable))
print(isinstance({457},Iterable))
print(isinstance(range(5),Iterable))
print(isinstance((i ** 2 for i in range(5)),Iterable))
print(isinstance(34,Iterable)) # False
print(isinstance(True,Iterable)) # False
# 2.
print(isinstance([34],Iterator)) # False
print(isinstance((34,),Iterator))
print(isinstance("agag",Iterator))
print(isinstance({"a":10},Iterator))
print(isinstance({457},Iterator))
print(isinstance(range(5),Iterator))
print(isinstance((i ** 2 for i in range(5)),Iterator))
print(isinstance(iter([34]),Iterator))
print(isinstance(iter((34,)),Iterator))
print(isinstance(iter("agag"),Iterator))
print(isinstance(iter({"a":10}),Iterator))
print(isinstance((i ** 2 for i in range(5)),Iterator))
四、高阶函数【重点掌握】
函数的本质:函数是一个变量,函数名是一个变量名,一个函数可以作为另一个函数的参数或返回值使用
如果A函数作为B函数的参数,B函数调用完成之后,会得到一个结果,则B函数被称为高阶函数
1.map()映射
"""
map(func,iterable):返回值是一个iterator
func:函数
iterable:可迭代对象,可以是多个,常用列表
功能:将iterable中的每一个元素传递给func,func返回一个结果,结果会成为迭代器中的元素
"""
# 1.需求:生成一个容器,其中的元素为1,4,9,16,25
# 方式一
list1 = [i ** 2 for i in range(1,6)]
print(list1)
# 方式二
def func1(a):
# print(a)
return a ** 2
r1 = map(func1,range(1,6))
print(r1) # <map object at 0x1096201d0>
print(list(r1))
# 方式三:推荐
list3 = list(map(lambda x:x ** 2,range(1,6)))
print(list3)
# 工作原理:range(1,6)-----》func映射----》[1, 4, 9, 16, 25]
# 练习:使用一行代码实现指定的效果:已知[2,7,3],转换为['2','7','3']
numlist = [2,7,3]
# 方式一
new_list1 = [str(num) for num in numlist]
print(new_list1)
# 方式二
new_list2 = list(map(lambda x:str(x),numlist))
print(new_list2)
# 2.
# 注意1:函数的参数由可迭代对象的个数决定
# 工作原理:会自动将多个可迭代对象中相同索引处的元素传递给指定的函数,进行相应的运算
# 注意2:多个可迭代对象中元素的个数可以不相同,使用的时候以少的可迭代对象作为参考
def func1(x,y,z):
return x + y + z
r21 = map(func1,[1,2,3],[4,5,6,1],[3,6,8,5])
print(list(r21))
r22 = list(map(lambda x,y,z:x + y + z,[1,2,3],[4,5,6,1],[3,6,8,5]))
print(r22)
# 3.map(func,iter)中的func可以是系统函数,也可以是自定义函数
2.reduce()减少
"""
reduce(func,seq):
func:函数
seq:序列
功能:将seq中的元素根据func指定的操作进行运算
工作原理:首先,将seq中的第0个和第1个元素传递给func,进行相应的运算,返回结果1,
接着,将结果1和seq中的第2个传递给func,进行相应的运算,返回结果2,
....
直到seq中的所有元素全部参与运算
eg:
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
calculates : ((((1+2)+3)+4)+5)
"""
"""
说明:
a.map:已知一个容器,通过func的映射关系,得到一个新的容器
b.reduce:已知一个容器,通过func的计算,得到一个数据
"""
from functools import reduce
# 1.需求:已知[1, 2, 3, 4, 5],求列表中元素的和
list1 = [1, 2, 3, 4, 5]
# 方式一
sum1 = sum(list1)
print(sum1)
# 方式二
def func1(x,y):
# print(x,y)
return x + y
sum2 = reduce(func1,list1)
print(sum2)
# 方式三
sum3 = reduce(lambda x,y:x + y,list1)
print(sum3)
# 练习:求15的阶乘
r = reduce(lambda x,y:x * y,range(1,16))
print(r)
# 注意:reduce(func,seq)中func的参数必须是两个
3.filter()过滤
"""
filter(func,iterable):返回值是一个iterator
func:函数
iterable:可迭代对象
功能:将iterable中的每个元素依次传递给func,如果func返回True,则表示需要保留,否则表示需要过滤掉
"""
"""
说明:
a.map:已知一个容器,通过func的映射关系,得到一个新的容器
b.reduce:已知一个容器,通过func的计算,得到一个数据
c.filter:已知一个容器,通过func的返回值是否为True,得到一个新的容器
"""
# 需求:已知,过滤掉其中的奇数list1 = [234,5,6,7,8,51,100,56,7,8]
list1 = [234,5,6,7,8,51,100,56,7,8]
# 方式一
new_list1 = [n for n in list1 if n % 2 == 0]
print(new_list1)
# 方式二
def func1(x):
# if x % 2 == 0:
# return True
# return False
return x % 2 == 0
r1 = filter(func1,list1)
print(r1)
print(list(r1))
# 方式三
r2 = filter(lambda x:x % 2 == 0,list1)
print(list(r2))
r2 = filter(lambda x:True if x % 2 == 0 else False,list1)
print(list(r2))
4.sorted()排序
"""
总结:
不同点:
1.调用方式不同
列表.sort(key=func,reverse=True)
sorted(列表,key=func,reverse=True)
2.结果不同
sort():是在原列表内部排序的
sorted():生成了一个新的列表
相同点:
1.默认都是升序
2.如果需要降序,都只需要设置reverse=True
3.如果需要自定义排序规则,都需要给key赋值一个函数
"""
# 1.升序
list1 = [34,5,24,10]
list1.sort()
print(list1)
list1 = [34,5,24,10]
l1 = sorted(list1)
print(l1)
# 2.降序
list1 = [34,5,24,10]
list1.sort(reverse=True)
print(list1)
list1 = [34,5,24,10]
l1 = sorted(list1,reverse=True)
print(l1)
# 3.自定义排序规则
# a.系统函数
list1 = ['fafa','gatgagah','dd']
list1.sort(key=len)
print(list1)
list1 = ['fafa','gatgagah','dd']
r1 = sorted(list1,key=len)
print(r1)
# b.自定义函数
# 将列表按学生成绩从大到小排序
students = [
{'name': '小花', 'age': 19, 'score': 90, 'gender': '女', 'tel':
'15300022839'},
{'name': '明明', 'age': 20, 'score': 40, 'gender': '男', 'tel':
'15300022838'},
{'name': '华仔', 'age': 18, 'score': 90, 'gender': '女', 'tel':
'15300022839'},
{'name': '静静', 'age': 16, 'score': 90, 'gender': '不明', 'tel':
'15300022428'},
{'name': 'Tom', 'age': 17, 'score': 59, 'gender': '不明', 'tel':
'15300022839'},
{'name': 'Bob', 'age': 18, 'score': 90, 'gender': '男', 'tel':
'15300022839'}
]
students.sort(reverse=True,key=lambda subdict:subdict['score'])
print(students)
students = [
{'name': '小花', 'age': 19, 'score': 90, 'gender': '女', 'tel':
'15300022839'},
{'name': '明明', 'age': 20, 'score': 40, 'gender': '男', 'tel':
'15300022838'},
{'name': '华仔', 'age': 18, 'score': 90, 'gender': '女', 'tel':
'15300022839'},
{'name': '静静', 'age': 16, 'score': 90, 'gender': '不明', 'tel':
'15300022428'},
{'name': 'Tom', 'age': 17, 'score': 59, 'gender': '不明', 'tel':
'15300022839'},
{'name': 'Bob', 'age': 18, 'score': 90, 'gender': '男', 'tel':
'15300022839'}
]
new_students = sorted(students,reverse=True,key=lambda subdict:subdict['score'])
print(new_students)