今天换了师傅。江湖人称景女神^o^。 女师傅讲的比较细,原理的比较多。初学者来说有些难。但是基本功是必须要打牢的。努力!

迭代器

迭代器,迭代的工具
1 什么是迭代,指的是一个重复的过程,每一次重复称为一次迭代,并且每一次重复的结果是下一次重复的初始值
while True:
print("=====")

l = ["a","b","c",]
count = 0
while count < len(l):
count +=1

2 为什么要有迭代器?
对序列类型:str list tuple可以用索引取值,
但是对非序列类型,如元祖,set 文件内容,python必须为我们提供一种不依赖于索引的迭代取值的方式--->迭代器
dic = {"name":"jack","age":18,"hobbie":"readbook"}

3 可迭代对象:
有obj.__iter__ 这个方法的对象 就是可迭代对象
可迭代对象需要有多个值 有六种
str
list
tuplt
dict
set
file
可以使用__iter__方法 看一下是否是可迭代对象
如:str.__iter__


4 迭代器对象
file 文件类型是迭代器对象,只有满足__iter__方法,同时还要有__next__方法

总结:
1,可迭代对象不一定是迭代器对象
2,迭代器对象一定是可迭代的对象
3,调用obj.__iter__()方法,可以把可迭代对象变为迭代器对象
4,对于迭代器对象,执行__iter__方法得到的还是他本身 还是迭代器对象

变为迭代器对象后 就可以迭代取值了
d={"user":"jack","age":18,"sex":"man"}
d_iter = d.__iter__()
print(d_iter.__next__())
还可以写成这样:
d = {"a","b","c"}
d_iter = iter(d)
print(next(d_iter))

# for循环详解:
1,调用in后的l_iter = l.__iter__()
2,i = l_iter.__next__()
3,捕捉StopIteration异常,结束迭代。
l = ["a","b","c"]:
for i in l :
print(i)

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

缺点: 1 只能往后走,并且循环一遍就结束了。
2 不能统计值得个数,即长度

def eater(name):
print("%s ready to eat"%name)
while True:
food=yield
print("%s start to eat %s" %(name,food))

这种表达式需要先初始化才能执行
1 生成迭代器
e = eater("n=jack")
2 初始化:
e.send("None")
3 传值:
e.send("吃屎")

同时这个表达式还可以组合使用
food = yield food_list
这个food_list就是返回值。print可以得到这个值

生成器

生成器: generater
自己写的迭代器,就是一个生成器
py提供了两种自己写生成器(迭代器)的机制,生成器函数,生成器表达式
1 生成器函数:
yield
凡是带生成器关键字的就是生成器
生成器函数调用不会触发代码的执行,而是会返回一个生成器(迭代器)
想要执行需要使用过next来进行调用
def func():
print("aaaaa")
yield 1
print("bbbbbb")
yield 2
记录当前所在位置,等待下一次next来出发函数的调用

列子:
使用生成器监听文件输入的列子
####### 注意这个例子需要ctrl + s 保存一下输入的文件 才能显示监听文件输入的内容
####### mac系统需要写个python程序来往文件中输入,才能显示
import time
def listion_file():
with open("userinfo") as f:
while True:
line = f.readline()
if line:
yield print(line.strip()):
time.sleep(0.1)
g = listion_file
for i in g:
print(i)

关键字:send
定义,在执行next的过程中,传递一个参数给生成器函数的内部
def foo():
print(1111)
res1 = yield 1
print(22222,"res1:",res1)
res2 = yield 2
print(33333,"res2:",res2)
yield 3
g = foo()
res = next(g)
print(res)
g.send("alex")
g.send("jack")
从函数的外部向内部传参,但是在生成器第一次中不能send传值,需要先激活next一下。

例子
计算移动平均值:
月度的天平均收入
def argvs():
day = 0
sum_moeny = 0
while True:
moeny = yield avg
sum_moeny +=money
day +=1
avg = sum_moeny/day
g = argvs()
next(g)
g.send(200)
g.send(400)

### 预激生成器
每个生成器都需要next预激活,如果有多个生成器,就比较麻烦
可以写个装饰器来进行预激活,这个装饰器就叫预激生成器


### yield from
一般写法:
def generator_func():
for i in range():
print(i)
for o in "hello"
print(o)
可以写成:
def generator_func():
yield from range(5)
yield from "hello"

取值的方法:
1 next(g) 随时可以停止,最后一次会报错

2 for i in g:
print(g) 从头到尾遍历一次,不遇到break return不会停止

3 list 或 tuple 吧值放入列表或元祖,但是占用内存大。
print(list(g))

注意: 生成器不能直接next(生成器函数),必须要先生成生成器 然后在next使用
错误的:
print(next(func()))
正确的:
g = func()
print(next(g))
生成器特点: 节省内存,惰性计算,解决内存问题,和程序功能之间的解耦

  总结:
       1,yield 为我们提供了一种自定义迭代器对象的方法
2,yield 可以返回多个值 return 只能返回一次值
3,函数暂停与在继续的状态是yield帮我们保存的

三元表达式

def my_max(x,y):
x if x > y else y
在比如
name = inpurt("请输入您的名字:")
res = "SB" if name == "alex" else "NB"
print(res)

if右边是条件为真时返回的值,else左边就是为假返回的值。

列表生成器,生成器表达式

    列表推到式   数据小的时候可以使用这个。
ll = [i**2 for i in range(10)]
print(ll)
  直接把循环得到的i在for右边进行运算,得到的全部结果赋值给ll


生成器表达式 在数据庞大的时候 建议使用生成器表达式
gg = (i for i in range(10))
for i in gg:
print(i)
总结: 1 一个生成器 只能取一次,
   2 生成器在不找他要值得时候,始终不执行
   3 当他执行的时候,要以执行时候的所有变量值为准
两者主要区别是列表推到式用中括号括起来,生成器是用小括号括起来。

练习:
取出文件中最长行数:
with open("test.txt","r",encoding="utf-8") as f:
g = (len(line) for line in f)
print(max(x))
上面两行可以精简为一行
print(max(len(line) for line in f))

sum求和
print(sun(len(line) for line in f))
文件每一行的字符个数

递归

定义: 在调用一个函数的过程中,直接或者间接有调用该函数本身,称之为递归调用
递归必备的两个阶段:
1.递推
2.回朔

def func():
print("--->")
func()
func()
这个递归是死循环
最多就到1000层 python就不允许递归了
import sys
print(sys.getrecursionlimit)
sys.setrecursionlimit(2000)
这样可以修改最大允许递归多少层

下面的也是递归调用:
def func()
print("from func")
bar()
def bar():
print("from bar")
func()
bar()


递归的列子 先递推, 然后在回溯
def age(n)
if n == 1
return 18
return age(n-1) +2
res =age(5)
print(res)
这个就是n等于5 先逐层往下递推,满足n 等于1就返回age(1)等于18 然后回朔 age(2)等于20
最后结果就是26


递归列表的值
l = ["a","b","c","d","e",[1,2,3,4,["b","h","j"]]]

def func(l):
for item in l:
if type(item) is list:
func(item)
else:
print(item)


匿名函数

lambda 表达式
def add(a,b):
return a+b
可以写为:
add = lambda a,b: a+b
print(add(1,2))
求平方的方法可以写一行
for i in map(lambfa num : num**2,range(10)):print(i)

练习:
print(min(-2,3,-4,key=lambad num:num%2))

内置函数

内置函数
print()
len()
abs()
max()
min()
eval()
zip()
dir()
总共有68个
反射相关 2
基础数据类型相关 38
作用域相关 2
locals 本地命名空间
globals 全局命名空间
面向对象相关 9
迭代器/生成器 3
range
next
iter
其他函数 12
inpurt
print
可以指定分隔符 sep=";" 还可以去掉结尾换行符,end="" 不是每执行一个for循环就打印,加上Flush=True 就会实时打印
其实print实际上是写文件。需要发起系统调用才能操作文件,如果print与print之间间隔较快,print会先先缓存一下在打印出来
加上flush=True就不会等待了。
如果在字符串中加上\r 就会一直在第一行覆盖打印 相当于seek(0)
练习题:
进度条
hash
对可hash得数据类型进行hash之后会得到一个数字
在一次执行程序的执行过程中,对相同的可hash变量,哈希之后的结果几乎总是是不相同的。
hash 字典底层的存储,和set集合的去重机制都相关
print(hash("123456"))
print(hash("123456"))
id
查看一个变量的内存地址
import
引用模块
help
查看帮助信息比如这个变量怎么用,这个对象怎么用等
callable
查看是否可调用
def foo():pass
a = 1
callable(a) 返回Flose
callable(foo) 返回True
dir
查看一个变量所拥有的所有名字,不止方法。
print(dir("1"))

数据类型类:
bool

bin
转换为二进制 0b
oct
转换为8进制 0o
hex
转换为16进制 0x
abs
计算数字的绝对值,只能接收数字
divmod()
商余函数
print(divmod(10,2))
print(divmod(7,3))
print(divmod(9,7))
返回一个元祖,里面有两个值,一个是商几后一个是余几
round
精确到小数点几位,精确的几位。四舍五入
print(round(3.1415926,4))
pow
求平方, 可以放第三个参数,第三个参数就是取余
print(pow(2,3))
print(pow(3,2,2))
sum
求和 接收一个可迭代对象,后面可以写一个起始值 默认起始值是从0开始计算。
print(sum([1,2,3,4,5],20))
可以放入一个生成器(迭代器),这样可以节省内存。
print(sum(range(1,6)))
min
取最小值
print(ming(1,-2,3,-4,key=abs))
当两个最小值时取第一个
max
取最大值

序列
reversed
取反 只能传入一个序列的数据结构,新生成一个迭代器,返回值取反,同时不改变原本的数据顺序
reversed(ret)
用处:可以吧元祖reversed 然后在list这个元祖 可以都得到一个反转的元祖。
format
格式化输出,可以居中显示
format("text" <20) <20 ^20
bytes
字符串转bytes
ord
print(ord("a")) 小写的a-z从 97开始 + 26,大写的A-Z从65+26
转换为acsii对应的数字
chr
print(chr(97))
转换为acsii对应的字母
ascii
字符串转ascii码
repr
可以让一个数据的数据类型可以原形毕露
a = 1
b = "1"
rper(a)
rper(b)
len
统计长度
enumerate
接收一个容器类型,一般是元祖或列表,可以制定下标起始值
list1 = ["香蕉","苹果"]
for k,v in enumerate(list1,1)
print(k,v)
all
接收容器
判断数据类型是否存在False,如果存在就都为Flase
any
接收容器
判断数据类型中是否存在True类型,如果存在就都为True
zip
ret = zip([1,2,3,4],("a","b","c","d"),(4,5,6,7)) #拉链方法
返回一个可迭代函数
for i in ret:
print(i)
filter
可以吧列表(可迭代数据类型),逐个传入函数当作参数,进行操作。
list1 = [1,2,4,6,9,11,17]
def func(num)
if num %2 == 0:reture num
for i in filter(func,list1)
print(i)
去除空字符
ll = ['test', None, '', 'str', ' ', 'END']
def func(strs):
if strs and strs.strip():return True 如果是True就返回
for i in filter(func,ll)
print(i)
map
range(10) 求他的平方:
推到式简单;i**2 for i in range(10)
用map
def func(num):
return num **2
for i in map(func,range(10)):print(i)
就是把函数放到map里面去执行
sorted
先说一下key: 可以指定按abs绝对值, 可以指定len 等内置函数,来根据函数返回值来进行运算
l = [1,2,-3,-4,4,5,6]
l.sort(key=abs)
print(l)
使用sorted
new_l = sorted(l,key=abs)
print(new_l)
这个有些例外,直接返回值。

执行内置函数:
eval 执行字符串中的代码 同时有返回值,吧结果返回。 注意这个函数有安全风险! 传入恶意程序会执行。
eval(print("123"))

exec 执行字符串中的代码,但是没有返回值
exec(print("123"))


注意: min max sorted filter map 面试容易问到
posted on 2018-05-05 08:59  李云杰  阅读(154)  评论(0编辑  收藏  举报