Python基础Day16

Python迭代器和生成器

1.Python迭代器和生成器

1.1迭代器

  • 访问可迭代对象的工具 iter(obj)返回对象(实例) next(it)获取下一个可迭代对象的值
  • 迭代器只能往前不能后退
  • 用iter函数可以返回一个可迭代对象的迭代器
  • 用next可以获得迭代器的下一个值

1.2生成器

生成函数:
yield: 逐步生成值,不会一次返回多个值。 与return相比,yield返回的是可迭代对象,return不是。 当next()或for循环调用yield时,yield都会从上次停止的地方开始。

# 可迭代的对象
L = list(range(10))
it = iter(L)
# print(iter(L))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# #print(next(it))超出容量报错
while True:
    try:
        print(next(it))

    except:
        print('迭代结束')
        break
       
    
list01 = list(range(10))
#需求:将大于5的数取出
#需求2:查找奇数

'''
    解题方法一:一次达到目的
'''
def find01():
    for item in list01:
        if item > 5:
            yield item
            item += 1

def find02():
    for item in list01:
        if item %2 == 1:
            yield item
            item +=1

for data in find01():
    print(data)

print('111111')

for data in find02():
    print(data)

print('------')
'''
    封装-分  把不同的数据分割出来
'''

def condition01(it):
    return it > 5

def condition02(it):
    return  it %2 == 1

'''
    继承-隔  把相同的数据融合在一起
'''
def find(func):
    for ite in list01:
        if func(ite):
            yield ite

'''
    做-多态  实现不同的任务
'''
for data in find(condition01):
    print(data)

print('---')
for data in find(condition02):
    print(data)

1.3生成器表达式

语法:(表达式 for 变量 in 可迭代对象 [if 真值表达式])

#生成器对象 生成器和迭代器一样可以配套for循环语句使用

def myrange(stop):
    i = 0
    while i<stop:
        yield i
        i += 1

#print(myrange(10))
#print(next(myrange(10)))

for x in myrange(10):
    print(x)

Python函数式编程:

用一系列函数解决问题。

  • 函数可以赋值给变量,赋值后变量绑定函数。
  • 允许将函数作为参数传入另一个函数。
  • 允许函数返回一个函数。

1.函数作为参数

将核心逻辑传入方法体

1.1lambda表达式

一种匿名函数

  • 作为参数传递时语法简洁,优雅,代码可读性强。
  • 随时创建和销毁,减少程序耦合度。

定义: 变量 = lambda 形参: 方法体

调用: 变量(实参)

1.2内置高阶函数

将函数作为或返回值的函数

  1. map(函数,可迭代对象) - 使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。
  2. filter(函数,可迭代对象) - 根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
  3. sorted(可迭代对象, key=函数, reverse=True) - 排序,返回值为排序后的列表结果。
  4. max(可迭代对象, key = 函数) - 根据函数获取可迭代对象的最大值。
  5. min(可迭代对象,key = 函数) - 根据函数获取可迭代对象的最小值。
class Girl:
    list_girl = []# 类属性 存放所有美女信息
    def __init__(self,name,outlook,age,height):
        self.name = name
        self.outlook = outlook
        self.age = age
        self.height = height
        # print(self)
        #将实例对象存入列表中,目的是想以实例属性的方法去访问每个对象
        Girl.list_girl.append(self)



a1=Girl('阿珂',100,23,166)
a2=Girl('苏荃',92,32,154)
a3=Girl('双儿',90,25,178)
a4=Girl('小郡主',76,22,168)
a5=Girl('方怡',75,27,165)
a6=Girl('建宁',86,25,175)
a7=Girl('曾柔',67,24,163)


# 需求:查找所有高于160的
def fun01():
    for item in Girl.list_girl:
        if item.height > 160:
            yield item

# 需求:颜值大于90的
def fun02():
    for item in Girl.list_girl:
        if item.outlook > 90:
            yield item

for data in fun01():
    print(data.name)
    
for data in fun02():
	print(data.name)
	
'''
    封装 找不同点
    继承 找相同点
    多态 实现不同的目的
'''
def condition03(item):
    return item.height > 160


def condition04(item):
    return item.outlook > 90

def find01(func):
    for item in Girl.list_girl:
        if func(item):
            yield item


for girl in find01(condition03):
    print(girl.name,end='\t')

print('\n')

for girl in find01(condition04):
    print(girl.name)



'''
    高阶函数

'''
class Girl:
    list_girl = []# 类属性 存放所有美女信息
    def __init__(self,name,outlook,age,height):
        self.name = name
        self.outlook = outlook
        self.age = age
        self.height = height
        # print(self)
        #将实例对象存入列表中,目的是想以实例属性的方法去访问每个对象
        Girl.list_girl.append(self)
    def __str__(self):
        return f'{self.name}-{self.age}-{self.outlook}-{self.height}'





a01=Girl('阿珂',100,23,166)
a02=Girl('苏荃',92,32,154)
a03=Girl('双儿',90,25,178)
a04=Girl('小郡主',76,22,168)
a05=Girl('方怡',75,27,165)
a06=Girl('建宁',86,25,175)
a07=Girl('曾柔',67,24,163)

print(a01)

print('------')

#1. 打印所有对象的名称
for element in map(lambda item:item.name,Girl.list_girl):
    print(element)

print('-------')
#2. 获取所有颜值大于80的对象
for nice in filter(lambda item:item.outlook>80,Girl.list_girl):
    print(nice)

print('-------')
#3. 获取年龄最大的美女对象 (max返回最大值的对象)
print(max(Girl.list_girl,key=lambda item:item.age))

print('-------')
#4. 按颜值升序
for line in sorted(Girl.list_girl,key=lambda item:item.outlook):#reverse=True是降序,默认是False升序
    print(line)

2.函数作为返回值

2.1闭包

闭包是指引用了此函数外部嵌套函数的变量的函数 闭包就是能够读取其他函数内部变量的函数。只有函数内部的嵌套函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数,同时这个函数又引用了外部的变量。

条件:

  • 必须有一个内嵌函数 。
  • 内嵌函数必须引用外部函数中变量
  • 外部函数返回值必须是内嵌函数。

2.2装饰器

装饰器是一个函数,主要作用是来用包装另一个函数或类。在不修改被装饰的函数的源代码,不改变被装饰的函数的调用方式的情况下添加或改变原函数的功能。

'''
	语法
'''
def 装饰器函数名(fn):
    语句块
    return 函数对象

@装饰器函数名 <换行>
def 被装饰函数名(形参列表):
    语句块

当使用@mydeco语法装饰myfun函数时,实际上发生的是:

  1. myfun函数作为参数传递给了mydeco装饰器。
  2. mydeco内部,首先调用了fn(),即此时调用了myfun函数,产生了输出:“函数myfun被调用”。
  3. 接着,打印了"装饰器函数被调用了,并返回了fx"。
  4. 然后,mydeco装饰器返回了新的函数fx

因此,此刻myfun实际上被替换成了新的函数fx。这样的行为正是Python装饰器的特性之一:装饰器可以修改函数的行为,甚至完全替换被装饰的函数。

2.2.1基本装饰器

有参数的函数装饰器(在myfunc外加了一层)

def mydeco(fn):
    fn()
    print("装饰器函数被调用了,并返回了fx")
    def fx():
        print("fx被调用了")
        # return fn()
    return fx

@ mydeco
def myfun():
    print("函数myfun被调用")

myfun()
myfun()
2.2.2带参数的装饰器
def repeat(num):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(num):
                func(*args, **kwargs)
        return wrapper
    return decorator

@repeat(3)  # 应用装饰器,重复执行下面的函数3次
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")  # 调用被装饰的函数
  • repeat 是一个接受参数的装饰器工厂函数,它返回一个装饰器。
  • decorator 是真正的装饰器,它接受一个函数 func 作为参数。
  • wrapper 函数重复执行被装饰的函数 num 次。
  • 使用 @repeat(3) 应用装饰器,使 greet 函数被执行3次。

注意:带参数的装饰器需要三层函数,def wrapper(args, kwargs) 传入的是被修饰的函数的参数。

2.2.3装饰器链
def uppercase(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()
    return wrapper

def exclamation(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result + "!"
    return wrapper

@exclamation
@uppercase
def say_hello(name):
    return f"Hello, {name}"

greeting = say_hello("Bob")
print(greeting)  # 输出 "HELLO, BOB!"

具体的执行过程如下:

  1. 装饰器是从内到外依次应用的。在你的代码中,首先应用的是 @uppercase,然后是 @exclamation
  2. @uppercase 装饰器会先包裹 say_hello 函数,然后 @exclamation 装饰器再包裹已经被 @uppercase 包裹过的函数。

步骤详细如下:

  1. 首先 @uppercase 包装 say_hello 函数:
    • 调用 say_hello("Bob") 返回 "Hello, Bob"
    • @uppercase 装饰器的 wrapper 函数将结果转换为大写,变为 "HELLO, BOB"
  2. 然后 @exclamation 包装已经被 @uppercase 包装过的 say_hello 函数:
    • 调用 wrapper(即 @uppercase 装饰器的 wrapper 函数)返回 "HELLO, BOB"
    • @exclamation 装饰器的 wrapper 函数将结果加上一个感叹号,变为 "HELLO, BOB!"
2.2.4 类装饰器
class MyDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("Something is happening before the function is called.")
        result = self.func(*args, **kwargs)
        print("Something is happening after the function is called.")
        return result

@MyDecorator  # 应用类装饰器
def say_hello(name):
    print(f"Hello, {name}!")

say_hello("Charlie")  # 调用被装饰的函数
  • MyDecorator 是一个类装饰器,它接受一个函数 func 作为参数并在 __call__ 方法中执行额外操作。

  • 使用 @MyDecorator 应用类装饰器,它将包装 say_hello 方法,使其在调用前后执行额外操作。

  • 与基本装饰器类似

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值