Python笔记13-nonlocal和global&生成器&高阶函数

一、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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值