python-06笔记-函数高级特性

迭代

  • 可以通过 for 循环来遍历这个 list 或 tuple,这种遍历我
    们称为迭代(Iteration)
    只要是可迭代对象,无论有无下标,都可以迭代,比如 dict
    就可以迭代:
  • 通过 collections 模块的 Iterable 类型判断是否可以迭代

列表生成式

1~10之间所有偶数: range(2,11,2), 返回[2,4,6,8,10];
方法1: 代码笨重, 这种类型建议改写为列表生成式

import math
li = []
for r in range(2,11,2):
    square = math.pi * r * r
     li.append(square)
    print(li)

方法2: 列表生成式实现

print([math.pi * r * r for r in range(2,11,2)])

方法3: 列表生成式实现, 将要返回的操作抽象为一个函数.

    def square(r):
        res =  math.pi * r * r
        return res
    print([square(r) for r in range(2,11,2)])

找出1~10之间所有奇数, 并且返回一个列表, (所有的奇数转换为字符串)

print([str(i) for i in range(1,11,2)])

找出1~100之间所有的质数.
判断num是否为质数, 如果为质数, 返回True, 否则返回False;
什么是质数?
只能被1和本身整除的数, 就是质数.
方法:循环:
依次判断num能否被(2,num)整除,
如果能被其中一个数整除,不是质数.
当循环结束, 都没有发现能被整除的数, 那么就是质数.

        def isPrime(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)])

实现矩阵转置的两种方式

  1. 列表生成式
  2. 内置函数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)])
    

    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)))

集合生成式

s = {1,2,3,4,5,6,7}
print({i**2 for i in s })

字典生成式

  • 定义字典:

    • 定义空字典, {}, dict()
    • 赋值: d = {‘key’:’value’, ‘key1’:’value1’}
    • 初始化所有value值: fromkeys()
    • 根据已有的数据创建字典;
      假设有20个学生,学生分数在60-100之间,筛选出成绩在90分以上的学生

      import random
      stuInfo = {"westos"+ str(i):random.randint(60,100)
                  for i in range(20)}
      print({ name:score for name, score in stuInfo.items() if score > 90 })# 筛选出score>90
      

    假设已有若干用户名字及其喜欢的电影清单,现有某用户,已看过并喜欢
    一些电影,现在想找新电影看看,又不知道看什么好.
    思路:
    根据已有数据, 查找与该用户爱好最相似的用户,
    即看过并喜欢的电影与该用户最接近,
    然后从那个用户喜欢的电影中选取一个当前用户还没看过的电影进行推荐.

    userInfo = {
        'user1':{'file1', 'file2', 'file3'},
        'user2':{'file2', 'file2', 'file4'},
    } 
    
  • 不用字典生成式

    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)   })
    

    将字典的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()})
    

    大小写计数合并 : 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()})
    

生成器(列表生成式改写)

在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的 list,
从而节省大量的空间。
在 Python 中,这种一边循环一边计算的机制,称为生成器(Generator)
创建一个生成器的两种方式:
使用g.next()方法依次读取元素(麻烦)
使用 for 循环(推荐)

判断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,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)
** isinstance
print(isinstance(primeLi,Iterable))  # 判断是否可以for循环

生成器可以使用的方法:

  • 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()

** 历史
斐波那契数列(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:当函数中包含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))

生成器fib()执行的过程分析:

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

猜你喜欢

转载自blog.csdn.net/qq_42687283/article/details/81806688