基础知识(七)——高级特性

一.生成式与生成器。

1.列表生成式。
列表生成式是一个用来生成列表的特定语法形式的表达式。 是python提供的一种生成表的特定语法形式的表达式。
2.字典生成式:用来快速生成字典的
eg… s = {1,2,3,4,5,6,7}
print({i:i** 2 for i in s})
3.集合生成式:用来快速生成集合的
eg … s = {1,2,3,4,5,6,7}
print({i**2 for in s})

eg . 求50个数的平方。
在这里插入图片描述
运行结果:
在这里插入图片描述eg .(1) 求以r为半径的圆的面积和周长(r的范围是1到10)
(2)求100内的所有偶数。
在这里插入图片描述
运行结果为:
在这里插入图片描述
2.生成器。
1)定义:在python中,一边循环一边计算的机制,称为生成器。(Generator)
2)使用环境:
一般情况下不需要使用,当我们的性能受到限制时才需要使用,比如,在使用python读取一个10G 的文件,如果一次性将 10G的文件加载到内存处理的话(read方法),内存肯定会溢出,这时如果使用生成器把读写交叉处理进行。
3)如何创建生成器。
(1)列表生成式的改写
(2) 用yied关键字。
4)生成器的特点:
1)节约内存
2)迭代到下一次的调用时,所使用的参数都是第一次所保留下来的,即是说,在整个所有函数调用的参数都是第一次所保留的,而不是新创建的。
5)访生成器的方法:
(1)for 循环(最常用)
(2)next() next() ——用于测试

ps. return 和 yield 工作机制的不同点:
return :在函数中遇到return时,函数 就执行结束了
yield: 当调用next 方法时,函数运行,遇到yield时就停止运行,当再次调用next 方法时,会继续从上次停止的地方继续执行。

6)生成器的其他常用方法:
next() , send()

eg.简易聊天机器人:

def chat_robot():
    response = ''
    while True:
        receive = yield  response
        if "年龄" in receive:
            response = "不告诉你"
        elif "名字" in receive:
            response = "I am most beautiful man in the world"
        elif  receive.endswith("吗?"):
            response = receive.rstrip("吗?")
        else:
            response = "I can not understand you "
rebot = chat_robot()
next(rebot)
while True:
    send_data = input("用户1-->>:")
    if send_data == 'q' or send_data =='quit':
        print("再见,下次聊")
        break
    response = rebot.send(send_data)
    print("机器人-->>:",response)

运行结果为:
在这里插入图片描述

eg2 : 生产者-消费者模型:
在这里插入图片描述

实验代码如下:

import  time
def Cosumer(name):
    buy_mane = input("请输入需要购买的物品:")
    print("%s 需要购买 %s " %(name,buy_mane))
    while True:
        game = yield  buy_mane
        print("%s 购买%s 成功。"%(name,buy_mane))

def producer(name):
    cosumers = (Cosumer("消费者%s" %(i+1)) for i in range(10))
    for cosumer in cosumers:
        buy_name = next(cosumer)
        print("工程师 %s 正在生产 %s"%(name,buy_name))
        time.sleep(2)
        print("工程师 %s 成功生产 %s "%(name,buy_name))
        cosumer.send(buy_name)

def main():
    producer("root")

main()

实验结果如下:
在这里插入图片描述

二. 迭代器。

1 迭代器定义: 迭代器是访问容器中元素的一种方式。迭代器是一个可以记住 遍 历位置的对象.
迭代器对象从集合的第一个元素开始访问,直到所有元素被访问结束。
2.迭代器的判断条件可以进行 next() 函数调用并不断返回下一个值的对象。(Iterator)
3.可迭代对象:可以直接用作for 循环的对象。
(判断条件) 一类是集合数据类型eg . list , tuple, dict , set , str
一类是:generator 包括生成器和带yield 的generator function.

辨析:

在这里插入图片描述
1)生成器都是迭代器,但迭代器不一定是生成器。
2) 迭代器都是可迭代对象,但可迭代对象不一定全是迭代器。可以用iter() 来将可迭代对象转换成迭代器。

eg.迭代器的转换:
在这里插入图片描述
在这里插入图片描述
运行结果如下:

在这里插入图片描述

三. 装饰器

1.闭包:
定义:当在一个函数中定义一个函数的时候
(1)内部函数使用了外部函数的临时变量
(2)外部函数的返回值是内部函数的引用。
(3)

内部函数对外部函数作用域里变量的引用(非全局变量),则内部函数称为闭包。

eg . 在这里插入图片描述

运行结果:
在这里插入图片描述

2.装饰器
装饰器的本质是一个函数,这个函数是用来处理其他函数的,它可以让其他函数在不需要修改代码的前提下增加额外的功能更,因此装饰器的返回值也是一个函数对象,它常用于有切面需求的场景,就比如:插入日志,性能测试,事务处理,缓存,权限校验等应用场景

(ps . 装饰器的作用:
因为写代码要遵循开放封闭原则,它规定已经实现的功能代码不允许被修改,但可以被扩展。
1.封闭:已经实现的功能代码块
2. 开放:对扩展开放

装饰器的功能:1)引入日志
2)函数执行时间统计
3)执行函数后的清理功能
4)执行函数前的预备处理
5) 权限效验等场景
6)缓存

示例一:好的日志对一个软件的重要性是显而易见的。如果函数的入口都要写一行代码来记
录日志,这种方式实在是太低效了。 那么请你创建一个装饰器, 功能实现函数运 行时自动产生日志记录。 日志格式如下:
程序运行时间 主机短名 程序名称: 函数[%s]运行结果为[%s]
产生的日志文件并不直接显示在屏幕上, 而是保存在file.log文件中, 便于后期 软件运行结果的分析.
代码如下:

import os
import time
import sys


# 装饰器: 用来添加日志信息的

    def add_log(login):
    
        def wrapper(*args, **kwargs):  
            # 获取被装饰的函数的返回值
            result = login(*args, **kwargs)
            # 返回当前的字符串格式时间
            now_time = time.ctime()
            # 获取主机名 nodename='foundation0.ilt.example.com'
            hostname = os.getenv("computername").nodename.split('.')[0]
            # 运行的程序
            process_full_name = sys.argv[0]
            process_name = os.path.split(process_full_name)[-1]
            # 日志内容
            # info = "正在运行程序: " + str(fun)
            # 获取函数名: 函数名.__name__
            info = "函数[%s]的运行结果为%s" % (login.__name__, result)
            log = " ".join([now_time, hostname, process_name, info])
            print(log)
            return result
    
        return wrapper
    @add_log
    def logmessagge():
        print("程序运行时间:%s ,主机名:%s,程序名称:%s,函数[%s]的运行结果为%s" %now_time,hostname,process_name,info,result))
    
    logmessagge()

装饰器1: 添加高速缓存的装饰器num_cache 如果第一次计算F(5) =F(4) + F(3) = 5 第二次计算F(6) =F(5) + F(4) 显然F(5)已经计算过了, F(4)也已经计算了, 我们可否添加一个装饰器, 专门用 来存储费波那契数列已经计算过的缓存, 后期计算时, 判断缓存中是否已经计算过了, 如 果计算过,直接用缓存中的计算结果. 如果没有计算过, 则开始计算并将计算的结果保存在缓 存中.
装饰器2: 程序运行计时器的装饰器timeit
该装饰器用来测试有无高速缓存求斐波那契数列, 它们两者运行的时间效率高低.

实验代码如下:

import time
import json
import os

def timmer(fun):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = fun(*args, **kwargs)
        end_time = time.time()
        print("%s 运行时间为:%.5f " % (fun.__name__, end_time - start_time))
        return result

    return wrapper


def num_cache(fun):
    cache_filename = 'cache.txt'
    if os.path.exists(cache_filename):
        with open(cache_filename) as f:
            try:
                cache = json.load(f)
            except:
                cache = {}

    def wrapper(num):
        if num in cache:
            result = cache.get(num)
            return result
        else:
            result = fun(num)
            cache[num] = result
            return result

    return wrapper


@num_cache
def fib(num):
    if num <= 2:
        return 1
    return fib(num - 1) + fib(num - 2)


@timmer
def fun1():
    result = fib(20)
    print("F[20] = ", result)


@timmer
def fun2():
    result = fib(35)
    print("F[35] = ", result)


fun1()
fun2()

运行结果为:
在这里插入图片描述

模块与包练习题: 微信好友数据分析与展示
1. 已知itchat可以获取好友的信息, 此处
统计好友的省份分布; 2. 获取分布好友最多的5个省份; 3. 将省份分布的数量基于pyecharts模块以条形图的方式展示; 附加需求: 将每个省份的好友备注名(RemarkName)存入依次存入对应省份的文 件中; e.g. 文件: 陕西省.txt 文件: 山东省.txt
4. 将上述 编写的代码封装为模块, 并实现模块的制作与发布;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值