当前位置: 首页 > news >正文

Python Day4

迭代器:迭代的工具

#1 什么是迭代:指的是一个重复的过程,每一次重复称为一次迭代,并且每一次重复的结果是下一次重复的初始值

#2 为什么要有迭代器?
#对于序列类型:str,list,tuple,可以依赖索引来迭代取值,
#但是对于dict,set,文件,python必须为我们提供一种不依赖于索引的迭代取值的方式-》迭代器

#3 可迭代的对象(下列都是):obj.iter

name='egon'
l=[1,2,3]
t=(1,2,3)
d={'name':'egon','age':18,'sex':'male'}
s={'a','b','c'}
f=open('a.txt','w',encoding='utf-8')

name.__iter__
l.__iter__
t.__iter__
d.__iter__
s.__iter__
f.__iter__

#4 迭代器对象(文件是):obj.iter,obj.next

f.__iter__
f.__next__

#总结:
#1 可迭代对象不一定是迭代器对象
#2 迭代器对象一定是可迭代的对象
#3 调用obj.iter()方法,得到的是迭代器对象(对于迭代器对象,执行iter得到的仍然是它本身)

#for循环就是依赖的将可迭代对象转换为迭代器对象,然后进行迭代

#总结迭代器的优缺点:
#优点:
#1、提供一种统一的、不依赖于索引的取值方式,为for循环的实现提供了依据
#2、迭代器同一时间在内存中只有一个值——》更节省内存,

#缺点:
#1、只能往后取,并且是一次性的
#2、不能统计值的个数,即长度

l=[1,2,3,4,5,6]
l[0]
l[1]
l[2]
l[0]

l_iter=l.__iter__()
# print(l_iter)
print(next(l_iter))
print(next(l_iter))
print(next(l_iter))

生成器

#1 什么是生成器:只要在函数体内出现yield关键字,那么再执行函数就不会执行函数代码,会得到一个结果,该结果就是生成器
#生成器就是迭代器

#yield的功能:
#1、yield为我们提供了一种自定义迭代器对象的方法
#2、yield与return的区别1:yield可以返回多次值 #2:函数暂停与再继续的状态是由yield帮我们保存的

#模拟tail -f access.log |grep 404

import time
def tail(file):
    with open(file,'rb') as f:
        f.seek(0,2)
        while True:
            line = f.readline()
            if line:
                yield line
            else:
                time.sleep(0.05)

lines=tail('access.log')

def grep(lines,pattern):
    for line in lines:
        line = line.decode('utf-8')
        if pattern in line:
            print(line)

grep(tail('access.log'),'404')

#了解知识点:yield表达式形式的用法

def eater(name):
    print('%s 开始吃饭' %name)
    food_list=[]
    while True:
        food=yield food_list #food=yield='鸡丁'
        food_list.append(food)
        print('%s start to eat %s' %(name,food))

e=eater('dzm')
#需要先初始化
next(e)
#然后e.send:1 从暂停的位置将值传给yield  2、与next一样
print(e.send('米饭'))
print(e.send('鸡丁'))

三元表达式

def my_max(x,y):
    if x > y:
        return x
    else:
        return y

res=my_max(10,20)
print(res)

#示例一

x=10
y=20
res=x if x > y else y

print(res)

#示例二

name=input('>>: ').strip()

res='sb' if name == 'alex' else 'nb'
print(res)

列表推导式

#示例一

l=[]
for i in range(1,11):
    res='egg'+str(i)
    l.append(res)

print(l)

l=['egg'+str(i) for i in range(1,11)]
print(l)

#示例二

l1=['egg'+str(i) for i in range(1,11) if i >= 6]
print(l1)

l1=[]
for i in range(1,11):
    if i >= 6:
        l1.append('egg'+str(i))

生成器表达式

#把列表推导式的[]换成()就是生成器表达式
#生成器比较节省内存

g=('egg'+str(i) for i in range(0,1000000000000000000000000000000000))
print(g) #显示结果g是个生成器
print(next(g))
print(next(g))
print(next(g))

#示例
with open('a.txt','r',encoding='utf-8') as f:
#求文件a.txt中最长的行的长度(长度按字符个数算,需要使用max函数)
print(max(len(line)for line in f))

#求文件a.txt中总共包含的字符个数
print(sum(len(line) for line in f))


递归

#递归调用:在调用一个函数的过程中,直接或者间接又调用该函数本身,称之为递归调用
#递归必备的两个阶段:1、递推 2、回溯
#python中的递归效率低,需要在进入下一次递归时保留当前的状态,在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己,但是python又没有尾递归,且对递归层级做了限制

#举例,计算age(5)的数值

# age(5) = age(4) + 2
# age(4) = age(3) + 2
# age(3) = age(2) + 2
# age(2) = age(1) + 2
#
# age(1) = 18

def func(n):
    if n == 1:
        return 18
    else:
        return func(n-1)+2

res=func(5)
print(res)

#总结递归的使用:
#1. 必须有一个明确的结束条件
#2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
#3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)


二分法

#了解的知识点
l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表,找到301

def search(l,num):
    print(l)
    if len(l) == 0:
        print('没有这个内容')
        return
    mid_index = len(l) // 2
    if num > l[mid_index]:
        search(l[mid_index+1:],num)
    elif num < l[mid_index]:
        search(l[0:mid_index],num)
    else:
        print(num)

x=int(input('请输入数字: '))
search(l,x)

匿名函数

def func(): #func=内存地址
    print('from func')

func()

#上面这是有名函数

#举例
#内存地址

def my_sum(x,y):
    return x+y

#把上面有名函数变为匿名函数

#自带return返回值效果
print(lambda x,y:x+y)
#打印后得到一个内存地址

#给这个内存地址传参执行
print((lambda x,y:x+y)(1,2))
#得到3

#也可以:

func=lambda x,y:x+y
#print(func)
print(func(1,2))

#lambda匿名函数通常跟别的函数配合使用
#匿名意味着引用计数为0,使用一次就释放,除非让其有名字


内置函数(与匿名函数配合使用)

#max,min,sorted,map,reduce,filter
#上面的函数都遵循迭代器对象
#next一次取一次值

#字典的运算:最小值,最大值,排序

salaries={
    'egon':3000,
    'alex':100000000,
    'wupeiqi':10000,
    'yuanhao':2000
}

#zip 拉链

s='hello'
l=[1,2,3]
g=zip(s,l)

#g是一个内存地址
#zip的结果是一个迭代器

print(list(g))
#结果
[('h', 1), ('e', 2), ('l', 3)]

#使用列表形式表现出来,从结果可以看出一一对应的保存在一个小元祖中

#max函数
#举例,求上面字典中工资最高的人名

#方法1,可以和上面的zip函数配合
g=zip(salaries.values(),salaries.keys())
#这样就可以按照薪资value比较,字典默认按照keys比较
print(max(g))
#结果
(100000000, 'alex')

#方法2,与匿名函数配合
print(max(salaries,key=lambda x:salaries[x]))
#结果:
alex
#'key='表示指定max函数比较的依据
#'k'是前面每次循环salaries后得到的字典的key,salaries[k]的结果返回给前面的key
#也就是说这里使用字典中的value进行比较,但显示的还是比较后结果所对应的字典中的key

#min函数
#用法跟max相同
print(min(salaries,key=lambda k:salaries[k]))

#sorted 排序
#与max用法相同
print(sorted(salaries,key=lambda k:salaries[k]))
#还可以加个reverse=True将结果反转
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))

高阶函数

map函数 映射

map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回

例1:

def f(x):
    return x * x

r = map(f, [1,2,3,4,5,6,7,8,9])
r = list(r)

print(r)

[1, 4, 9, 16, 25, 36, 49, 64, 81]

map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list

例2:

list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']

例3:

names = ['AAA', 'BBB', 'CCC']

g = map(lambda name: '%s_傻子' % name, names)

print(list(g))

['AAA_傻子', 'BBB_傻子', 'CCC_傻子']

filter 过滤

和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

例如,在一个list中,删掉偶数,只保留奇数,可以这么写:

def is_odd(n):
    return n % 2 == 1

list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 结果: [1, 5, 9, 15]

把一个序列中的空字符串删掉,可以这么写:

def not_empty(s):
    return s and s.strip()

list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))
# 结果: ['A', 'B', 'C']

可见用filter()这个高阶函数,关键在于正确实现一个“筛选”函数。

注意到filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list

与lambda配合使用

names=['AAA_SB', 'BBB_SB', 'CCC_SB','egon']
g=filter(lambda x:x.endswith('SB'),names)
print(list(g))

['AAA_SB', 'BBB_SB', 'CCC_SB']

reduce

reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

比方说对一个序列求和,就可以用reduce实现:

from functools import reduce

def add(x, y):
    return x + y

x = reduce(add, range(1, 101))

print(x)

5050

当然求和运算可以直接用Python内建函数sum(),没必要动用reduce

与lambda配合:

from functools import reduce
print(reduce(lambda x,y:x+y,range(1,101)))

5050

内置函数

#需要掌握

#divmod 得到商和余

print(divmod(10001,25))
(400, 1)

#只要余不为0就需要加1

#enumerate
#对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值
#enumerate多用于在for循环中得到计数

l=['a','b','c']
for i,v in enumerate(l):
    print(i,v)

#结果:

0 a
1 b
2 c

#enumerate还可以接收第二个参数,用于指定索引起始值,如:

list1 = ["这", "是", "一个", "测试"]
for index, item in enumerate(list1, 1):
    print(index, item)

#结果:
1 这
2 是
3 一个
4 测试

#补充
#如果要统计文件的行数,可以这样写:
#利用enumerate():

count = 0
for index, line in enumerate(open(filepath,'r')):
    count += 1

#eval
#将字符串str当成有效的表达式来求值并返回计算结果
#将字符串转成相应的对象,转换成列表,转换成字典,转换成元组等

res=eval('[1,2,3]')
print(res,type(res))

#结果:
[1, 2, 3] &lt;class 'list'&gt;

#pow

res=pow(2,3,3) #2的三次方的结果对3取余
print(res)

#结果:
2

#round 四舍五入

print(round(3.5))
4

#slice 切片
#制造一个切片格式

l=['a','b','c','d','e','f']
s=slice(1,5,2)
print(l[s])

#结果:
['b', 'd']

转载于:https://blog.51cto.com/dzm911/2054711

相关文章:

  • Monty Hall 问题与贝叶斯定理的理解
  • 更改backend
  • 39条常见的Linux系统简单面试题
  • mybatis动态sql中的trim标签的使用
  • 开源一个封装AFNetworking的网络框架 - SJNetwork
  • 我的学习计划
  • 03 UITableView 刚进来的时候无法滚动到到底部
  • Asp.Net WebApi服务端解决跨域方案
  • 029——VUE中键盘语义修饰符
  • Google 是如何开发 Web 框架的
  • 46.2. HTML 处理
  • delphi2010 开发及调试WebService 实例
  • pyhon3.0 day01 变量、输入、输出、循环
  • 【BZOJ3675】【APIO2014】序列分割 [斜率优化DP]
  • 使用redux开发的简单步骤
  • 【译】JS基础算法脚本:字符串结尾
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • Angular Elements 及其运作原理
  • CAP理论的例子讲解
  • css的样式优先级
  • C语言笔记(第一章:C语言编程)
  • Flex布局到底解决了什么问题
  • gops —— Go 程序诊断分析工具
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • js ES6 求数组的交集,并集,还有差集
  • js对象的深浅拷贝
  • js如何打印object对象
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • Mac转Windows的拯救指南
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • mysql_config not found
  • React-生命周期杂记
  • vue的全局变量和全局拦截请求器
  • Windows Containers 大冒险: 容器网络
  • 仿天猫超市收藏抛物线动画工具库
  • 高程读书笔记 第六章 面向对象程序设计
  • 关于 Cirru Editor 存储格式
  • 简单数学运算程序(不定期更新)
  • 两列自适应布局方案整理
  • 那些被忽略的 JavaScript 数组方法细节
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 微信小程序开发问题汇总
  • 优化 Vue 项目编译文件大小
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • AI算硅基生命吗,为什么?
  • ionic入门之数据绑定显示-1
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 阿里云服务器购买完整流程
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 翻译 | The Principles of OOD 面向对象设计原则
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • 如何用纯 CSS 创作一个货车 loader
  • ​iOS实时查看App运行日志
  • ​业务双活的数据切换思路设计(下)
  • #define、const、typedef的差别