欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

我的python之旅呀-10高级特性

程序员文章站 2022-03-29 14:41:30
...

一、生成式

1、定义

生成式就是一个用来快速生成特定语法形式的表达式。
列表生成式:用来快速生成列表
字典生成式:用来快速生成字典
集合生成式:用来快速生成集合

2、语法格式

(1)普通的语法格式:[exp for iter_var in iterable]
(2)带过滤功能语法格式: [exp for iter_var in iterable if_exp]
(3)循环嵌套语法格式: [exp for iter_var_A in iterable_A for iter_var_B in iterable_B]
例如:

#(1)普通的语法格式:[exp for iter_var in iterable]
# 需求: 生成10个1~50之间的随机数值。
import random
def list_expression(count=10, start=0, end=50):
    return  [random.randint(start, end) for count in range(count)]
    
print(list_expression())

#(2)带过滤功能语法格式: [exp for iter_var in iterable if_exp]
# 需求: 找出1-50之间能被3整除的数值;
def list_expression(start=1, end=50, div_num=3):
    return [num for num in range(start, end + 1) if num % div_num == 0]
    
print(list_expression())

    
#(3)循环嵌套语法格式: [exp for iter_var_A in iterable_A for iter_var_B in iterable_B]
nums = [item1+ item2 for item1 in 'abc' for item2 in '123']
print(nums)

运行结果:
我的python之旅呀-10高级特性

#集合生成式
# 需求: 生成10个1~20之间的随机且不重复数值。
import random
nums = {random.randint(1, 20) for count in range(10)}
print(nums)

3、生成式练习

# (1)求以r为半径的圆的面积和周长(r的范围从1到10)
import math
def circle_area(r):
    return  math.pi * pow(r,2)
def circle_perimeter(r):
    return 2 * math.pi * r

area =  [circle_area(r) for r in range(1, 11)]
perimeter = [circle_perimeter(r) for r in range(1,11)]
print(area)
print(perimeter)
#(2)找出1~100之间所有的质数
def is_prime(num):
    """判断是否为质数"""
    for i in range(2, num):
        if num % i == 0:
            return False
    else:
        return True

def find_prime():
    """找出1~100之间所有的质数"""
    return [num for num in range(1, 101) if is_prime(num)]

if __name__ == '__main__':
    result = find_prime()
    print(result)
#(3)将字典的key值和value值调换
def swap_key_value(dictObj):
    return {value: key for key, value in dictObj.items()}

if __name__ == '__main__':
    d = {
        'user1': 'passwd1',
        'user2': 'passwd2',
    }
    result = swap_key_value(d)
    print(result)
#字典key值大小写计数合并 : 已知字典{'A':10, 'b':5, 'a':2}, 合并后为{'a':12, 'b':5} 
#注意: key值最终全部为小写
dict = {'A':10, 'b':5, 'a':2}
d = {key.lower(): (dict.get(key.lower(), 0) + dict.get(key.upper(), 0)) for key, value in dict.items()}

print(d)

二、生成器

1、定义和特点

(1)在python中,一边循环一边计算的机制,称为生成器(Generator)
(2)应用场景:
性能限制需要用到,比如读取一个10G的文件,如果一次性将10G的文件加载到内存处理的话 (read方法),内存肯定会溢出。但使用生成器把读写交叉处理进行,比如使用(readline和readlines) 就可以再循环读取的同时不断处理,这样就可以节省大量的内存空间
(3)特点:
1> 解耦。 爬虫与数据存储解耦;
2> 减少内存占用.。随时生产, 即时消费, 不用堆积在内存当中;
3> 可不终止调用.。写上循环, 即可循环接收数据, 对在循环之前定义的变量, 可重复使用;
4> 生成器的循环, 在 yield 处中断, 没那么占 cpu

2、创建和访问

(1)创建
方法一:列表生成式的改写。 []改成()
方法二:yield关键字
(2)访问:
方法一:通过for循环, 依次计算并生成每一个元素
方法二:通过 next() 函数一个一个获取

# 生成器创建方法一:
nums_gen = (num for num in range(1, 10001) if num % 8 == 0)
print(nums_gen)             # <generator object <genexpr> at 0x7f8f2cb92350>
print(type(nums_gen))       # <class 'generator'>

# 查看一个对象是否可以for循环?
from collections.abc import  Iterable
print("生成器是否为可迭代对象?", isinstance(nums_gen, Iterable))

# 访问方法一: 通过for循环, 依次计算并生成每一个元素。
"""
for num in nums_gen:
    if num > 50:
        break
    print(num)
"""

# 访问方法二: 如果要一个一个打印出来,可以通过next()函数获得。
print(next(nums_gen))       # 执行一次next生成一个值
print(next(nums_gen))
print(next(nums_gen))
# 生成器创建方法二: 函数中包含yield关键字
def fib2(num):
    """不使用递归方式实现Fib数列,返回前num个fib数"""
    count = 0
    a = b = 1
    while True:
        if count < num:
            count += 1
            yield a
            a, b = b, a + b
        else:
            break
# 如果函数中有yield关键字, 那么函数的返回值是生成器对象.
result = fib2(100)
print(result)

(3)比较yield和return,理解yield的工作原理
return:
遇到return, 函数就执行结束。 后面的代码不会执行

def return_example():
	print('step 1')   #打印 'step 1'
	return True     
 	print('step 2')   # 不执行

yield:
函数中包含yield关键字, 返回的是生成器对象
当第一次调用next(genObj), 才开始执行函数内容。
遇到yield关键字, 执行停止
再次调用next方法时, 从上次停止的代码位置继续执行。
遇到yield关键字, 执行停止。

def yield_example():
    for count in range(100):
        yield 'step' + str(count + 1)
        print("success")

if __name__ == '__main__':
   result = yield_example()
   print(next(result))
   print(next(result))

运行结果:
我的python之旅呀-10高级特性

3、生成器的send方法

用于给生成器传递数据

def grep(kw):
    """搜索关键字"""
    while True:
        response = ''
        request = yield response    # 生成器
        if kw in request:           # 判断关键字是否在生成器中
            print(request)
if __name__ == '__main__':
    grep_gen = grep('python')
    next(grep_gen)
    # send方法可以给生成器传递数据, 并一直执行, 遇到yield停止。
    grep_gen.send('I love python')  #将字符串传递给生成器,并用request来接收
    grep_gen.send('I love Java')

案例:聊天机器人

def chatRobot():
    response = ''
    while True:
        request = yield  response
        if '姓名' in request:            # 判断关键字是否在用户的输入中
            response = '姓名暂时保密'      # 如果在,将字符串赋给response,并用response来接收,打印Robot: response
        elif '你好' in request:
            response = 'hello'
        else:
            response = '我不知道你在说些什么, 请换种说法'

if __name__ == '__main__':
    Robot = chatRobot()    # 生成器对象
    next(Robot)            # 调用next方法
    while True:
        request = input("Me:  ")
        if request == '再见':
            print("欢迎下次聊天.....")
            break
        response = Robot.send(request)   #将用户输入的request传给生成器,用request来接收
        print("Robot:  ", response)

聊天机器人进阶版:使用青云客智能聊天机器人API
我的python之旅呀-10高级特性
我的python之旅呀-10高级特性

#代码需要联网运行
# requests库是python实现的最简单易用的HTTP库,多用于网络爬虫。
#安装 pip install requests
import requests
# json库是进行数据交换
import json

def robot_api(word):
    # 青云客提供的聊天机器人API地址
    url = 'http://api.qingyunke.com/api.php?key=free&appid=0&msg=%s' %(word)
    try:
        # 访问URL,通过get()方法,返回一个响应对象(网址的内容),存起来,再通过.text返回文本信息
        #在交互式环境可以演示,返回的文本信息是一个字符串
        response_text = requests.get(url).text
        # 将json字符串转成字典, 并获取字典的‘content’key对应的value值
        # eg: {'result': 0, 'content': '有做广告的嫌疑,清静点别打广告行么'}
        return  json.loads(response_text).get('content', "无响应")
    except Exception as e:
        # 如果访问失败, 响应的内容为''
        return  ''


def chatRobot():
    response = ''
    while True:
        request = yield  response
        if '姓名' in request:
            response = '姓名暂时保密'
        elif '你好' in request:
            response = '你好!Hello'
        else:
            response = robot_api(request)

if __name__ == '__main__':
    Robot = chatRobot()   # 生成器对象
    next(Robot)           # 调用next方法
    while True:
        request = input("Me: ")
        if request == '再见':
            print("欢迎下次聊天.....")
            break
        response = Robot.send(request)
        print("Robot: ", response)

4、生成器应用案例:

(1)生产者-消费者模型
(2)发布-订阅模型

三、生成器、迭代器、可迭代对象总结

生成式:快速生成列表,集合,字典
生成器(generator):一边循环一边计算
迭代器(iterator):可以调用next()方法访问元素
可迭代对象:可以通过for循环访问

生成器都是迭代器,都是可迭代对象
可迭代对象不一定是迭代器,例如:str,list,tuple,set,dict
怎么将可迭代对象转换成迭代器:通过iter()关键字
我的python之旅呀-10高级特性

四、闭包

1、定义

闭包就是指有权访问另一个函数作用域中的变量的函数。
常见形式:
(1)函数嵌套
(2)内部函数使用外部函数的变量
(3)外部函数的返回值是内部函数的名称
应用场景:装饰器
优点:提高代码可复用性

def line_conf(a, b):
    """y = ax + b """
    def line(x):
        return a * x + b
    return line          #返回的line 是一个函数

# line1是一个函数名
line1 = line_conf(2, 3)  # 调用函数, a=2, b=3
line2 = line_conf(3, 3)  # 调用函数, a=3, b=3
line3 = line_conf(4, 3)  # 调用函数, a=4, b=3

# x = [1, 3, 5, 7 ,9]
x = list(range(1, 10, 2))
y1 = [line1(item) for item in x]
y2 = [line2(item) for item in x]
y3 = [line3(item) for item in x]

print(y1)
print(y2)
print(y3)
相关标签: python