python笔记-0508

本文介绍了Python中的迭代器、生成器和装饰器。迭代器是实现__iter__和__next__方法的对象,用于节约内存。生成器是迭代器的一种,包含yield关键字,可用于生成斐波那契数列。装饰器是闭包函数,用于不修改原函数情况下扩展其功能。文中还详细讲解了各种装饰器的创建和使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、迭代器
1、迭代器:拥有__iter__和__next__方法的对象就是迭代器。

2、迭代:是访问集合元素的一种方式,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫迭代。

3、可迭代协议:内部实现了__iter__方法。

4、迭代器协议:必须拥有__iter__方法和__next__方法。

5、能被for循环的内容:list,dic,str,set,tuple,f.open(),range(),enumerate

6、dir()方法能获取对应数据类型的所有方法。例如:print(dir([]))

①利用dir()查看共有方法

a = set(dir([])) & set(dir({})) & set(dir("")) & set(dir(range(1)))
print(a) #{'__gt__', '__iter__', '__ge__', '__delattr__', '__new__', '__contains__', '__le__', '__str__', '__init_subclass__', '__init__', '__class__', '__setattr__', '__eq__', '__sizeof__', '__getitem__', '__getattribute__', '__lt__', '__hash__', '__subclasshook__', '__dir__', '__reduce__', '__format__', '__repr__', '__ne__', '__doc__', '__len__', '__reduce_ex__'}

②判断int类型是否有__iter__方法。

print("__iter__" in dir(int))  #False

7、iter()方法的作用:返回一个迭代器。

a = [1,2,3,4,5]
b = a.__iter__()
print(b) #<list_iterator object at 0x00000000020E7470>处理list对象的迭代器位于XX地址
print(next(b))  #1,运行一次迭代器,输出1

8、打印迭代器中的方法:

a = set(dir([].__iter__())) - set(dir([])) #求差值
print(a) #{'__length_hint__', '__setstate__', '__next__'}

9、for循环原理
①for循环一个可迭代对象(实现__iter__方法)
②__iter__方法返回一个迭代器(迭代器实现了__iter__和__next__方法)
③for先判断对象哪些范围需要迭代,然后调用迭代器的__next__方法获取值

10、迭代器作用:节约内存

11、数据类型转换:例如元组和列表间的转换底层,就是使用迭代器实现的

a = "hello"
b = list(a)
print(b) #['h', 'e', 'l', 'l', 'o']

c = (1,2,3)
d = list(c)
print(d) #[1, 2, 3]

12、利用迭代器,生成斐波那契数列

class Fib():
    def __init__(self,num):
        self.num = num
        self.a = 1
        self.b = 1
        self.current = 1
    def __iter__(self):
        return self  #返回自己,调用自己的__next__方法
    def __next__(self):
        if self.current <= self.num:
            a = self.a
            self.a,self.b = self.b,self.a + self.b
            self.current += 1
            return a
        else:
            raise StopIteration
for i in Fib(10):
    print(i,end = " ") #1 1 2 3 5 8 13 21 34 55 89

二、生成器

1、生成器:本质就是迭代器。生成器包括两种,生成器函数和生成器表达式。

2、生成器函数:一个包含yield关键字的函数,就是生成器函数。并且,yield不能和return公用,yeild只能在函数内使用。
①生成器函数执行后,会得到一个生成器作为返回值,并不会执行函数体。
②执行了__next__方法后,才会执行函数体,并获得返回值。
③next()内置方法,内部调用生成器函数的__next__方法
④yield和ruturn相同的是,都可以返回值,但是不同的是,yield不会结束函数

3、创建一个生成器函数,执行,得到一个生成器,并调用

def func():      #创建生成器函数
    for i in range(5):
        yield i  #包含yield,是生成器函数
a = func() #执行生成器函数,得到一个生成器
print(next(a)) #0 执行生成器,得到返回值
print(next(a)) #1
print(next(a)) #2

4、创建一个生成器生成器,定义多个yield值

def func():      #创建生成器函数
    yield 1
    yield 3
    yield 2
a = func()     #调用生成器函数,得到生成器
print(next(a)) #1
print(next(a)) #3
print(next(a)) #2

5、创建生成器,生成5桶康师傅方便面

def ksf():
    for i in range(1,6):
        yield "生产第%d桶康师傅方便面"%i
a = ksf()
for i in a:
    print(i,end = " ") #生产第1桶康师傅方便面 生产第2桶康师傅方便面 生产第3桶康师傅方便面 生产第4桶康师傅方便面 生产第5桶康师傅方便面

6、sent():在获取下一个值的时候,给上一个yield的位置传递一个数据
①第一次使用生成器的时候,是用next获取第一个值
②最后一个yield不能接受外部的值

7、使用sent()方法给yield传递参数

def func():
    a = 0
    b = yield a
    print("----------",b)
    yield 9
    yield 3
a = func()
print(next(a))       #移到下一个yield并打印出来
b = a.send("123")    #给上一个yield的位置传递参数,并获得下一个yield值,赋值给b
print(b)
print(next(a))        #移到下一个yield并打印出来

8、利用生成器,和sent()方法,计算移动平均值

def avrage1():
    count = 1
    get_num = 0
    avg = 0
    sum = 0
    while True:
        get_num = yield avg
        sum += get_num
        avg = sum / count
        count += 1

a = avrage1()
next(a)           #到达第一个yield的位置
print(a.send(10)) #10.0
print(a.send(20)) #15.0
print(a.send(30)) #20.0

9、利用yield from遍历出可变数据类型中的数据

def func():
    yield from "abc"   #遍历字符串的所有元素
    yield from range(3) #遍历数字范围内的所有数字

a = func()  #调用函数
b = list(a) #将函数转化为列表类型
print(b) #['a', 'b', 'c', 0, 1, 2]

10、生成器表达式:

a = (i for i in range(5)) #创造一个生成器表达式
print(a) #返回一个生成器

b = [i for i in range(5)] #列表推导式
print(b)

11、利用生成器表达式,模拟老母鸡下蛋

a = ("鸡蛋%d"%i for i in range(1,10)) #生成器表达式
print(list(a))

12、生成器作用:可以实现多任务。

三、装饰器

1、装饰器:本质是一个闭包函数。

2、作用:在不修改原函数及其调用方式的情况下,对原函数功能进行扩展

3、闭包函数
①闭包函数必须有内嵌函数
②内嵌函数必须引用外层函数的变量
③闭包函数必须返回内嵌函数的函数名

4、创建一个闭包函数

5、判断是否闭包函数的方法__closure__,如果是,输出含有cell的数据,如果不是,返回None

def outer(tax):
    def inner(a):
        c = a * tax  #调用外层函数的变量
        return c
    print(inner.__closure__)  #判断是否是闭包函数
    return inner    #返回内嵌函数的函数名

a = outer(0.1) #调用闭包函数,传递外层参数
b = a(100)    #调用内嵌函数,传递参数
print(b)      #打印返回值

6、语法糖@
格式:@装饰器名称

7、创建一个计算函数执行花费时间的闭包函数

import time
def timer(x):  #装饰器
    def inner():
        start = time.time()
        x()
        end = time.time()
        print(end - start)
    return inner
@timer #语法糖,相当于func = timer(func)
def func():
    sum = 0
    for i in range(10000000):
        sum += i
    print(sum)

func()

8、创建一个带返回值的装饰器

import time
def timer(func):
    def inner():
        start = time.time()
        a = func()     #接受返回值
        end = time.time()
        print(end - start)
        return a       #返回返回值
    return inner
@timer
def fun():
    print("abc")
    return "ok..."    #设置返回值

a = fun()
print(a)

9、创建一个可以传递任意参数的装饰器

def decor(x):                 #创建装饰器
    def inner(*args,**kwargs):
        print("**********")  #打印格式
        x(*args,**kwargs)
        print("**********")  #打印格式
    return inner
@decor
def vocal_concert(*args,**kwargs):
    print(args)
    for i in args:
        print(i,end = " ")
    print()
    for k,v in kwargs.items():
        print(k,v)
    print("演唱会")

vocal_concert("刘德华","张惠妹",age = 30,address = "广州")

10、创建带返回值的可以传递任意参数的装饰器

def decor(x):
    def inner(name,date,address):
        print("**************************************")
        y = x(name,date,address)
        print("**************************************")
        return y
    return inner
@decor
def func(name,date,address):
    print("{},{},{},地表最强演唱会".format(name,date,address))
    return "不见不散"
a = func("周杰伦","2019-5-8","广州")

11、使用@wraps(func)解决被装饰函数的信息不能查看的问题

from functools import wraps  #导入wraps方法
def decor(x):
    @wraps(x)                 #解决不能查看注释的bug
    def inner(name,date,address):
        print("**************************************")
        y = x(name,date,address)
        print("**************************************")
        return y
    return inner
@decor
def func(name,date,address):
    """
    :param name:
    :param date:
    :param address:
    :return:
    """
    print("{},{},{},地表最强演唱会".format(name,date,address))
    return "不见不散"
a = func("周杰伦","2019-5-8","广州")
print(func.__doc__)  #显示参数
print(func.__name__) #显示函数名

12、给函数添加多个装饰器

def decor1(func):
    def inner():
        print("11111")
        func()
        print("22222")
    return inner

def decor2(func):
    def inner():
        print("33333")
        func()
        print("44444")
    return inner

@decor1
@decor2

def hello():
    print("hello")
hello()

13、@property装饰器:把一个方法调用方式变成属性调用方式。将一个方法当成属性使用。
①只能在面向对象中使用。
②可以直接调用被装饰的函数的函数名
③只能装饰不带参数的方法

14、@property装饰器私有方法的getter和setter方法。

class Stu():
    def __init__(self,name,age):
        self.name = name
        self.__age = age
    @property              #getter方法
    def message(self):
        print("运行getter")
        return self.__age
    @message.setter        #setter方法
    def message(self,x):
        print("运行到setter")
        self.__age = x

a = Stu("张三",19)
a.message = 28
print(a.message)

15、使用@property装饰器,求圆形的周长和面积

from math import pi
class Circle():
    def __init__(self,r):
        self.r = r
    @property
    def perimeter(self):
        return 2 * pi *self.r
    @property
    def area(self):
        return pi * self.r * self.r
a = Circle(10)
print(a.perimeter) #62.83185307179586
print(a.area)      #314.1592653589793

16、使用@property装饰器,BMI指数

class People():
    def __init__(self,name,sex,weight,height):
        self.name = name
        self.sex = sex
        self.weight = weight
        self.height = height
    @property
    def BMI(self):
        return self.weight / (self.height ** 2)

a = People("张三","男",70,1.85)
print(a.BMI) #20.45288531775018

四、类的各种方法

1、对象方法

2、静态方法

class A():
    count = 0
    def __init__(self,name):
        self.name = name
        A.count += 1
    def duixiangfangfa(self):
        print("对象方法")
    @staticmethod
    def jingtai():
        print("静态方法")
    @classmethod
    def leifangfa(cls):
        print("类方法,调用类属性 count = ",cls.count)
a = A("李白")
a.duixiangfangfa()
A.jingtai()
a.jingtai()
A.leifangfa()

3、类方法

class Goods():
    __discount = 1  #类属性
    def __init__(self,name,price):
        self.name = name      #对象属性
        self.__price = price  #对象属性
    @classmethod   #类方法
    def change_discount(cls,new_discount):
        cls.__discount = new_discount
    @property
    def price(self):
        return self.__price * self.__discount

a = Goods("苹果",10)
print(a.price)

Goods.change_discount(0.8)  #调用类方法
print(a.price)

b = Goods("香蕉",10)
print(b.price)

作业

1、迭代器练习,找质数

class PrimeNumbers:
    def __init__(self, start, end):  #初始化对象属性
        self.start = start
        self.end = end

    def isPrimeNum(self, k):  #如果是质数,返回True
        if k < 2:
            return False
        for i in range(2, k):
            if k % i == 0:
                return False
        return True

    def __iter__(self):    #生成迭代器
        for k in range(self.start, self.end + 1):
            if self.isPrimeNum(k):
                yield k

for x in PrimeNumbers(1, 100):
    print(x)

2、生成器练习

def read_file(fpath):
    BLOCK_SIZE = 6
    with open(fpath, 'r') as f:
        while True:
            block = f.read(BLOCK_SIZE)
            if block:
                yield block
            else:
                return

import os
g = read_file(os.getcwd() + '\\aa.txt')
for content in g:
    print(content)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值