一.生成式与生成器。
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. 将上述 编写的代码封装为模块, 并实现模块的制作与发布;