Python-----列表,字典,集合生成式,生成器

1.列表生成式

列表生成式使用变形:

 [i**2 for i in range(2,10,2) ]                                  ##拿出1~10之间的偶数,并执行函数i**2

[fun(i) for i in range(2,10,2)]                                  ##拿出1~10之间的偶数,并执行函数fun(i)

 [i**2 for i in range(2,10,2) if i%3==0]                 ##拿出1~10之间的偶数,如果i能够被3整除,执行函数i**2

 [fun(i) for i in range(2,10,2) if i%3==0]               ##拿出1~10之间的偶数,如果i能够被3整除,执行函数fun(i)

 [fun(i) for i in range(2,10,2) if isFun(i)]               ##拿出1~10之间的偶数,如果满足函数fun(i),执行函数fun(i)

[fun1(i) if isFun(i) else fun2(i) for i in range(2,10,2)]##拿出1~10之间的偶数,满足函数fun(i),执行函数fun1(i)否则执行函数fun2(i)


import math
 【1】 找出1~10之间所有偶数, 并且返回一个列表, (包含以这个偶数为半径的圆的面积)
 1~10之间所有偶数: range(2,11,2), 返回[2,4,6,8,10];
方法1: 代码笨重, 这种类型建议改写为列表生成式
li = []
for r in range(2,11,2):  #[2,4,6,8,10]
     square = math.pi * r * r
     li.append(square)
 print(li)

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器
方法2: 列表生成式实现
 print([math.pi * r * r for r in range(2,11,2)])

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器

方法3: 列表生成式实现, 将要返回的操作抽象为一个函数.
def square(r):
    res =  math.pi * r * r
    return res
print([square(r) for r in range(2,11,2)])

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器
 【2】 找出1~10之间所有奇数, 并且返回一个列表, (所有的奇数转换为字符串)
print([str(i) for i in range(1,11,2)])

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器
【3】 找出1~100之间所有的质数.
def isPrime(num):
 判断num是否为质数, 如果为质数, 返回True, 否则返回False;
 什么是质数?
 只能被1和本身整除的数, 就是质数.
  方法:循环:
                 依次判断num能否被(2,num)整除,
                 如果能被其中一个数整除,不是质数.
                 当循环结束, 都没有发现能被整除的数, 那么就是质数.
   
    for i in range(2, num):
        if num % i == 0:
            return  False
    else:
        return True

print([i for i in range(2,101) if isPrime(i)])

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器

 【4】 找出1~100之间所有奇数, 并且返回一个列表                

(如果能被3整除, 返回返回该数的平方, 否则返回该数的三次方)

print([i**2 if i%3==0 else i**3 for i in range(1,101,2)])

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器

【 5】给定一个列表li = [2,3,4,5,6,3,1,4,5]
      如果是偶数返回0, 如果是奇数返回1

print([0 if i%2==0 else 1 for i in range(li)])

例题:

 (2017-腾讯-在线编程题)

- 题目描述:

给定一个正整数,编写程序计算有多少对质数的和等于输入的这个正整数,并输出结果。输
入值小于1000。
如,输入为10, 程序应该输出结果为2。(共有两对质数的和为10,分别为(5,5),(3,7))
[2,3,5,7]


输入包括一个整数n,(3 ≤ n < 1000)

输出描述:
输出对数

num = int(input("N:")) 
 判断2~num之间有多少个质数?
def isPrime(num):
    for i in range(2, num):
        if num % i == 0:
            return  False
    else:
        return True
primeLi =  [i for i in range(2,num) if isPrime(i)]
print(primeLi)


 判断素数列表primeLi中有多少个素数对等于num
primePairCount = 0

 [2,3,5,7]
思路, 效率不高:
先从列表中拿出两个数;
 判断两个数之和是否等于num
 for item1 in primeLi:
     for item2 in primeLi:
         if item1 + item2 == num and item1 <= item2:
             primePairCount += 1
 print(primePairCount)

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器

 思路:
 [2,3,5,7]   2===== 10-2; 3====10-3, 5====10-5, 7====10-7
for item1 in primeLi:
    if (num -item1) in primeLi and item1 <= num-item1:
        primePairCount += 1
print(primePairCount)

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器

实现矩阵转换

实现矩阵转置的两种方式

列表生成式
 内置函数zip

li = [
    [1,2,3,3,4],
    [4,5,6,2,1],
    [7,8,9,1,2]
]
方法1:
print([[ row[columnIndex] for row in li] for columnIndex in range(5)])

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器

columnIndex=0=====> 返回的是每一行的第0个索引值; [1,4,7]
columnIndex=1=====> 返回的是每一行的第0个索引值; [2,5,8]

 方法2:
     *li: 解包
     zip:
1).打包函数, 用于将可迭代的对象作为参数,
    将对象中对应的元素打包成一个个元组,
    然后返回由这些元组组成的列表。

2).如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,
    利用 * 号操作符,可以将元组解压为列表
3). zip 方法在 Python 2 和 Python 3 中的不同:
   在 Python 3.x 中为了减少内存,zip() 返回的是一个对象。
   如需展示列表,需手动 list() 转换。

   print(list(zip(*li)))

2.字典生成式


 1. 随机生成电影清单
 import random
 data = {}   # 存储用户及喜欢电影清单的信息;
 for userItem in range(100):
     files = set([])
     for fileItem in range(random.randint(4,15)):
         files.add( "film" + str(fileItem))
     data["user"+str(userItem)] = files
 print(data)

import pprint
pprint.pprint({
    "user"+str(userItem):
        {"film" + str(fileItem) for fileItem in range(random.randint(4,15))}
        for userItem in range(100)   })

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器

 3. 将字典的key值和value值调换;
d = {'a':'apple', 'b':'bob', 'c':'come'}

print({v:k for k,v in d.items()})
print({k:k.upper() for k,v in d.items()})

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器
 4.大小写计数合并 : key值最终全部为小写.

d1 = {'A':10, 'b':3, 'a':5, 'B':8, 'd':1}

print({k.lower(): d1.get(k.upper(),0)+d1.get(k.lower(),0) for k,v in d1.items()})

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器
 print({k.lower(): d1[k.upper()]+d1[k.lower()] for k,v in d1.items()})  # 报错

3.集合生成式

s = {1,2,3,4,5,6,7}
 集合生成式
print({i**2 for i in s })
 字典生成式
print({i:i**2 for i in s })

4.生成器列表生成式的改写

1). 判断2~num之间有多少个质数?
def isPrime(num):
    for i in range(2, num):
        if num % i == 0:
            return  False
    else:
        return True
 primeLi =  [i for i in range(1,15) if isPrime(i)]
 print(primeLi)

 

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器

# 生成器最快实现的方式:通过列表生成式改写. 一边循环, 一边计算的机制.
primeLi =  (i for i in range(2,1000) if isPrime(i))
# print(next(primeLi))
# print(next(primeLi))
# print(next(primeLi))
# print(next(primeLi))

from collections import  Iterable
for i in primeLi:
    print(i)

print(isinstance(primeLi,Iterable))  # 判断是否可以for循环

5.Fibnnian数列

** 历史
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)
以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,
斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*)
在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963年起出版了以
《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。


** 数列内容
斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,
610,987,1597,2584,4181,6765,10946,17711,28657,46368........

yield: 当函数中包含yield关键字, 返回值是一个生成器, 如果要执行函数内容.需要调用next方法, 或者for循环.
           运行过程: 当执行next方法时, 遇到yield程序停止, 直到执行下一次next方法时,
          从上一次停止的yield处继续执行,遇到yield停止运行.
 return: 遇到return函数执行结束;

 num=1
def fib(num):
    """将来显示几个fib数列"""
     count代表显示的已经
     a代表第一个数, b代表第二个数, count代表已经显示的fib个数,当前为0.
    a,b,count = 0,1,0
     如果当前显示的个数小于需要显示的格式, 则显示b, 并且计算出下一个要显示的数。
    while count < num:
        yield  b
        a, b = b, a+b
        # 已经显示的次数加1;
        count += 1


 生成器: 如果函数中有yield, 那么这个函数的返回值就是一个生成器;
res=fib(100)
print(next(res))
print(next(res))

Python-----列表,字典,集合生成式,生成器

生成器fib()执行的过程分析:
执行语句 f = fab(100) 时,并不会马上执行 fib() 函数的代码块,而是首先返回一个 iterable 对象(即生成器)!
在 for 循环语句执行时或者next(),才会执行 fib() 函数的代码块。
执行到语句 yield b 时,fib() 函数会返回一个迭代值,直到下次迭代前,
程序会回到 yield b 的下一条语句继续执行,然后再次回到 for 循环,如此迭代直到结束。
看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
由此可以看出,生成器通过关键字 yield 不断的将迭代器返回到内存进行处理,而不会一次性的将对象全部放入内存,
从而节省内存空间。

6.生成器实现迷你机器人聊天

 生成器可以使用的方法:

 - next(g)
- g.send(''), 给生成器传递值;
 给yield所在位置发送一个数据, 直到遇到下一个yield停止.

 

 def fun():
     while True:
         print("welcome......")
         receive = yield  "hello"
         print(receive)
fun返回值是一个生成器对象.(因为函数中包含yield关键字)
 f = fun()
 print(f)
 print(next(f))
 f.send("微信")

def chat_robot():
    res = ''
    while True:
        receive = yield res
        if 'age' in receive:
            res = "年龄保密"
        elif 'name' in receive:
            res = "siri"
        else:
            res = "i don't know what you say"

def main():
     生成器对象
    Robot = chat_robot()
    next(Robot)
    while True:
        send_data = input("粉条>>:")
        if send_data == 'q' or send_data == 'bye':
            print("不聊了, 我也撤了.....")
            break
        print(Robot.send(send_data))

main()

Python-----列表,字典,集合生成式,生成器

Python-----列表,字典,集合生成式,生成器

7.函数中的yield

def fun():
    print('step 1')
    yield "yield1"
    print('step 2')
    yield  'yield2'
    print('step3')
    res = yield 'yield3'  # res = "hello"
    print("生成器接收了一个值:", res)
    yield "yield4"

Python-----列表,字典,集合生成式,生成器
 1. 函数中有yield, 返回值是一个生成器.
g = fun()
print(g)

2. 生成器函数默认不执行函数内容, 当next(g)时, 才执行函数内容.
3. 执行函数时, 一直执行, 遇到yield停止。 默认情况不会显示yield后面的内容,
如果要显示print(next(g))
next(g)
print(next(g))
print(next(g))

4. 如果需要给生成器函数传值
(1). 必须有变量接收传递的值: res = yield 'yield3'
(2). 通过g.send("hello")
 (3). send方法, 给yield所在位置传值, 接收值之后, 直到遇到yield停止.
g.send("hello")