Python三大神器(迭代器、生成器、装饰器)和csv文件操作

三大神器和csv文件操作

迭代器

1.什么是迭代器(iter)
  1. 迭代器是容器型数据类型

  2. 特点:

    • 无法通过打印迭代器查看元素、也无法统计元素个数
    • 需要使用元素的时候必须将元素从迭代器中取出,取出以后该元素就从迭代器中消失
2.创建迭代器 - 将其他序列转换成迭代器
i1 = iter('hello')
i2 = iter([10, 20, 30, 40])
i3 = iter({'a': 10, 'b': 20})
i4 = iter({100, 200, 300})
print(i1)       # <str_iterator object at 0x7fc25598fc40>
print(i2)       # <list_iterator object at 0x7fb21888fc70>
print(i3)
print(i4)
# print(len(i1))        # 报错!TypeError: object of type 'str_iterator' has no len()
3.获取迭代器的元素

不管以什么的方式获取到了迭代器的元素,被获取到的元素一定会从迭代器中消失

  1. 获取单个元素: next(迭代器)

    i1 = iter('hello')
    print(next(i1))     # 'h'
    print(next(i1))     # 'e'
    print(next(i1))     # 'l'
    print(next(i1))     # 'l'
    print(next(i1))     # 'o'
    # print(next(i1))     # 报错!StopIteration
    
    result = list(i1)
    print(result)       # []
    
    i1 = iter('hello')
    print(list(i1))     # ['h', 'e', 'l', 'l', 'o']
    # print(next(i1))     # 报错!StopIteration
    
  2. 遍历

    i1 = iter('hello')
    for x in i1:
        print(f'x:{x}')
    
    print(list(i1))
    
    
    from re import finditer, findall
    result = finditer(r'(?i)[a-z](\d+)', '按时sh233数据==2231bhs901bb =8决胜巅峰23 sjn823')
    print(list(result))
    
    result = findall(r'(?i)[a-z](\d+)', '按时sh233数据==2231bhs901bb =8决胜巅峰23 sjn823')
    print(result)
    
    
    result = findall(r'(?i)([a-z])\d+\1', '按时sh233h数据==2231bhs901bb =8决胜巅峰23 sjn823n')
    print(result)
    
    result = finditer(r'(?i)([a-z])(\d+)\1', '按时sh233h数据==2231bhs901bb =8决胜巅峰23 sjn823n')
    print(result)       # <callable_iterator object at 0x7fdb35213f40>
    for x in result:
        print(x.group(2))
    

生成器

1.什么是生成器
  1. 生成器是一种容器,但是这个保存的不是多个数据,而是产生(创建)多个数据的算法
  2. 同时具有迭代器保存数据的特点:
    • 打印看不到内容
    • 不支持len操作
    • 元素也是取一个就少一个,而且不能再放回生成器中
  3. 注意:生成器获取元素和迭代器获取元素的方法一样
2.创建生成器

调用一个带有yield关键的函数就可以得到一个生成器对象

注意: 如果函数中有yield,那么调用这个函数不会执行函数体,也不会获取函数返回值,而是创建一个生成器对象

def func1():
    print('hello')
    yield
    return 100


result = func1()
print(result)
3.控制生成器产生数据的个数和值

生成器产生数据的个数和值,由执行函数体的时候会遇到几次yield,以及每次遇到yield的时候后的值来决定

def func2():
    yield 100
    yield 200
    yield 300


g1 = func2()
print(list(g1))     # [100, 200, 300]
# print(next(g1))   # 报错!StopIteration


def func3():
    for x in range(10):
        yield x*2


g2 = func3()


# 练习:创建学科学号的生成器,能产生从 'python001' 到 'python999' 的学号
def study_id(subject):
    for x in range(1, 1000):
        yield f'{subject}{x:0>3}'


g3 = study_id('python')
g4 = study_id('java')
print(next(g3))
print(next(g3))

print(next(g4))

print(next(g3))

print(next(g4))
4.生成器创建数据的原理

调用函数创建生成器的时候不会执行函数体,在通过生成器对象获取生成器中的元素的时候才会执行函数,而且每次在执行函数体的时候只会执行到yield就停止,并且记录停止的位置,下次再获取元素的时候从上次结束的位置接着执行。

def func4():
    print('======1======')
    yield 100
    print('======2======')
    yield 200
    print('======3======')
    yield 300


g4 = func4()
print(next(g4))
print(next(g4))
print(next(g4))


def func5():
    yield 100
    yield 200
    yield 300


# print(next(func5()))        # 100
# print(next(func5()))        # 100
g5 = func5()
print(next(g5))
print(next(g5))

装饰器(了解)

装饰器是用来给函数添加功能

  1. 通过直接修改原函数的代码可以给函数添加功能

    存在的问题:

    • 如果多个函数需要添加同样的功能,需要修改多个函数的代码,并且添加相同的代码
    • 如果想要取消添加的功能,又要重新修改多个函数的函数
  2. 使用装饰器

    写装饰器的套路:

    def 装饰器名(f):
        def new_f(*args, **kwargs):
            实现新增的功能
            result = f(*args, **kwargs)
            实现新增的功能
            return result
        return new_f  
    
    def count_time(f):
        def new_f(*args, **kwargs):
            start = time.time()
            result = f(*args, **kwargs)
            end = time.time()
            print(f'执行时间:{end-start}')
            return result
        return new_f
    
    
    @count_time
    def func1():
        print('hello world!')
    
    
    @count_time
    def func2(a, b):
        print(a + b)
    
    
    func1()
    func2(12, 23)
    
    
    # 写一个装饰器,将返回值是数字的原函数的返回值乘以10000
    def magnify(f):
        def new_f(*args, **kwargs):
            result = f(*args, **kwargs)
            if type(result) in (int,float):
                return result * 10000
            return result
        return new_f
    
    
    @magnify
    def func3(a, b):
        return a * b
    
    
    result = func3(4, 5)
    print(result)
    
    result = func3('abc', 2)
    print(result)
    
    
    class A:
        @classmethod
        def func1(cls):
            pass
    
        @staticmethod
        def func2():
            pass
    

csv文件操作

csv文件(逗号分隔值文件) - 让数据以表格的方式存储(更简单的表格文件)

使用时要导入:import csv

1.csv文件读操作
  1. 方法1 - 读文件内容得到一个迭代器,迭代器中的元素是每一行内容对应的列表

    • 创建reader对象: csv.reader(文件对象) - 创建文件对应的reader,并且获取文件内容

      注意:打开csv文件的时候需要给参数newline赋值为空串

      reader1 = csv.reader(open('files/2018年北京积分落户数据.csv', encoding='utf-8', newline=''))
      
    • 通过reader对象(本质是一个迭代器)获取文件内容

      print(next(reader1))     # ['id', 'name', 'birthday', 'company', 'score']
      print(list(reader1))
      
  2. 方法2 - 读文件内容得到一个迭代器,迭代器中的元素是每一行内容对应的字典(键是每一列的第一行数据)

    reader2 = csv.DictReader(open('files/2018年北京积分落户数据.csv', encoding='utf-8', newline=''))
    for x in reader2:
        print(x)
    
2.csv文件写操作
  1. 方法1 - 以列表为单位写入一行数据

    • 创建writer对象: csv.writer(文件对象)

      writer1 = csv.writer(open('files/students.csv', 'w', encoding='utf-8', newline=''))
      
    • 写入数据

      • writer对象.writerow(列表) - 一次写入一行数据
      • writer对象.writerows(元素是列表的列表) - 同时写入多行数据
      writer1.writerow(['学号', '姓名', '年龄', '电话', '分数'])
      writer1.writerows([
          ['stu001', '小明', 19, '110', 98],
          ['stu002', '张三', 23, '199', 72],
          ['stu003', '小花', 22, '1728', 78]
      ])
      
  2. 方法2 - 以字典为单位写入一行数据

    • 创建DictWriter对象: csv.DictWriter(文件对象, 字典的键)

      writer2 = csv.DictWriter(
          open('files/dogs.csv', 'w', encoding='utf-8', newline=''),
          ['狗名', '年龄', '品种', '价格']
      )
      
    • 将字典的键作为文件内容写入文件的第一行

      writer2.writeheader()
      
    • 写入数据

      • writer对象.writerow(字典) - 一次写入一行数据
      • writer对象.writerows(元素是字典的列表) - 同时写入多行数据
      writer2.writerow({'狗名': '旺财', '年龄': 3, '品种': '哈巴狗', '价格': 500})
      writer2.writerows([
          {'狗名': '猜猜', '年龄': 2, '品种': '哈士奇', '价格': 1500},
          {'狗名': '土豆', '年龄': 1, '品种': '土狗', '价格': 50},
          {'狗名': '妞妞', '年龄': 3, '品种': '金毛', '价格': 2500}
      ])
      
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值