作业
```python
# 1.用生成器完成自定义range方法,可以完成系统range的所有功能
# def my_range(start, end=None, step=1):
# if step > 0: # 往后遍历
# if end is None:
# start, end = 0, start
# while True:
# if start >= end:
# break
# yield start
# start += step
# else: # 10, 5, -1 => [10, 5) # 往前遍历
# while True:
# if start <= end:
# break
# yield start
# start += step
# for v in my_range(10, 2, -2):
# print(v) # [0, 9]
# for v in my_range(5, 10):
# print(v) # [5, 9]
# for v in range(5):
# print(v) # [0, 4]
# for v in range(5, 10):
# print(v) # [5, 10)
# for v in range(10, 5):
# print(v) # 无结果
# for v in range(10, 5, -1):
# print(v) # [10, 5)
# for v in range(5, 10, -1):
# print(v) # 无结果
# for v in range(5, 10, 0):
# print(v) # 无结果
# 2.用生成器完成自定义enumerate方法,也可以为可迭代对象提供索引支持
def my_enumerate(iterable, start=0): # 原就是可迭代对象,终就是在原遍历结果上添加一个索引
for v in iterable:
yield (start, v)
start += 1
for v in my_enumerate({'a': 1, 'b': 2}.items(), start=100): # str,list,tuple,set,dict,dict.keys()|.values()|.items()
print(v)
print('------------------------------')
for v in enumerate({'a': 1, 'b': 2}.items(), start=100): # str,list,tuple,set,dict,dict.keys()|.values()|.items()
print(v)
# 5! = 5 * 4 * 3 * 2 * 1
# # 3.用生成器完成获取阶乘得方法,
# 第一次next得到1的阶乘,
# 第二次next得到2的阶乘,依次类推,直接for循环,
# 可以依次得到指定范围内得所有阶乘,eg:factorial(10),可以得到1~10之间的10个阶乘
def my_factorial(num): # 5
# yield 1
# yield 1 * 2
# yield 1 * 2 * 3
# yield 1 * 2 * 3 * 4
# yield 1 * 2 * 3 * 4 * num
pro = 1
for n in range(1, num + 1):
pro *= n
yield pro
# pro = n = 1
# while True:
# if n > num:
# break
# pro *= n
# yield pro
# n += 1
for v in my_factorial(5):
print(v)
```
# 复习
```python
'''
1.迭代器:不需要索引的取值方式
2.生成器:通过特殊的语法自定义的迭代器
3.枚举对象:为可迭代对象创建索引(按照迭代的顺序创建索引)
迭代器对象:装有多个值的容器
)可以通过__next__()进行取值
)取一个少一个
)通过__iter__()得到的还是自身
优点:可以不用依赖索引的统一取值方式(可以产生装有无限个元素的容器)
缺点:只能从前往后,一次只能取一个(不能获取元素个数)
可迭代对象:可以被迭代的对象
)可以通过__iter__()转换为迭代器
for循环迭代器:
) 自动获取操作对象的迭代器对象
) 内部一次调用一个__next__()获取值
) 取到末尾(不能再取)自动处理异常,结束循环
for v in [].__iter__():
print(v)
# 重点:1.for的工作原理,2.有哪些可迭代对象
# 思考:迭代器对象能不能按索引取值(有限的可以考虑一下,无限的免谈)
obj = enumerate('abc')
print(obj)
obj = list(obj)
print(obj[0])
可以将有限的直接强转为list进行索引取值
# 枚举对象
for i, v in enumerate('abc', 100): # 可迭代对象,起始编号
print(i, v)
结果:
100 a
101 b
102 c
生成器:
)结构通过函数方式实现
)函数内部返回值不是通过return,而是通过yield
)生成器(函数)名 + () 不是调用函数,而是得到生成器对象(自定义迭代器对象)
)可以通过__next__()进行取值,取值一次进入到下一个yield
'''
def fn():
# 为得到第一个yield结果的逻辑代码
yield 1
# 为得到第二个yield结果的逻辑代码
yield 2
# ...
yield 3
# ...
yield 4
obj = fn()
print(obj) # generator object
print(list(obj))
def func():
count = 0
while True:
yield count
count += 1
obj1 = func()
print(obj1)
# print(list(obj1)) 无限个
for v in [1, 2, 3, 4]:
pass
for v in fn():
pass
for v in range(1, 5):
pass
print(next(obj1))
print(next(obj1))
# obj1.close()
# print(next(obj1))
print('--------------------------------')
def fn3():
# yield
msg = yield
print(msg)
# 下方的yield可能需要外界的参数
yield
obj3 = fn3()
# next(obj3)
print(next(obj3)) # 停在第一个yield
try:
obj3.send('message')
except StopIteration:
print('取完了')
# send总结:
# 1.为当期停止的yield传参,所以传参前必须停在某一个yield上
# 2.下一次yield就可以使用send传入的参数,可以形成依赖传入的参数的相关返回值
# 3.send除了发生信息给当期停止的yield,内部还调用了一次__next__()方法
```
## 三目运算符
# 三元运算符:就是 if...else...语法糖
# 前提:if和else只有一条语句
# 原
# cmd = input('cmd: ')
# if cmd.isdigit():
# print('可以转化为数字')
# else:
# print('不可以转化为数字')
# 简化
# cmd = input('cmd: ')
# print('可以转化为数字') if cmd.isdigit() else print('不可以转化为数字')
# 案例:得到两个数大值
a = 20
b = 30
res = a if a > b else b # 求大值
print(res)
# 三元运算符的结果不一定要与条件直接性关系
res = 'b为小值' if a > b else 'a为小值' # 求小值
print(res)
# -------------------------------------------------------------------
```
## 推导式
```python
# 列表推导式:[v for v in iterable]
dic = {'a': 1, 'b': 2, 'c': 3} # => [('a', 1), ('b', 2), ('c', 3)]
res = [(k, v) for k, v in dic.items()]
# 字典推导式:{k: v fro k, v in iterable}
ls = [('a', 1), ('b', 2), ('c', 3)] # => {'a': 1, 'b': 2, 'c': 3}
res = {k: v for k, v in ls}
# 元组推导式
# res = ((k, v) for k, v in dic.items())
print(tuple(res))
# 案例
# range(10) # 可以被推导为列表
res_ls = [arg for arg in range(10)]
print(res_ls)
res_dic = {'a': arg for arg in range(10)}
print(res_dic)
# 迭代出可解压为的单列容器可以推导出字典
res_dic = {v: k for k, v in enumerate('abc')}
print(res_dic)
```
## 递归
```python
# ***
# 递归:回溯与递推
# 回溯:询问答案的过程
# 递推:推出答案的过程
# 本质:函数的自我调用
# 直接:自己调自己
# 间接:自己调别人,别人最终由调回自己
# 前提:*****
# 回溯到一个有具体结果的值,开始递推
# 回溯与递推的条件要有规律
# 递归本质:函数的自我调用(自己调自己)
# import sys
# sys.setrecursionlimit(100) # 手动设置递归深度
# print(sys.getrecursionlimit()) # 默认1000
# count = 0
# 自己调自己
# def a():
# global count
# count += 1
# if count > 50:
# return
# a()
# a()
# 函数间接调用自己:一旦形成循环调用,就产生了递归
def b():
c()
def c():
d()
def d():
b()
b()
# 询问第一个人年龄,回溯条件 小两岁,第五个人说出自己的年龄,推导出第一个人年龄
# 条件:下一个人的年龄比这个人年纪大两岁
def get_age(num): # 得到年龄
if num == 1:
return 58
age = get_age(num - 1) - 2
return age
res = get_age(5)
print(res)
# 阶乘
# 5! = 5 * 4! 4! = 4 * 3! ... 2! = 2 * 1
def factorial(num):
if num == 1:
return 1
temp = num * factorial(num - 1)
return temp
res = factorial(5)
print(res)
```
## 匿名函数
# 匿名函数:没有名字的函数
# 语法:lambda 参数列表: 一个返回值表达式
# 匿名函数:没有函数名,没有函数体,只有一个返回值
# 关键字:lambda | 参数列表省略() | 返回值return关键字也被省略
# f = lambda x, y: (x + y, x - y)
# print(f)
# print(f(10, 20))
# 应用场景:
# 1.匿名函数函数地址可以被一个变量接受,该变量就可以作为函数名来使用,但就违背了匿名初衷
# 2.结合内置函数来使用: 内置函数某些参数需要一个函数地址,
# -- 可以赋值一个有名函数名,也可以直接赋值匿名函数
# res = max(10, 20, 50, 30)
# print(res)
# res = max({10, 20, 50, 30})
# print(res)
def fn(arg):
print(arg)
return arg
ls = [100, 200, 50, 10]
res = max(ls, key=fn)
print('------------------------')
print(res)
res1 = max(ls, key=lambda ele: ele)
print(res1)
# max
iterable = [1, 5, 3, 2, 7]
res = max(iterable, key=lambda x: x) # 参数:可迭代对象遍历的元素;返回值:做比较的值
print(res)
# 薪资最高
iterable = {
'Bob': 12000,
'Tom': 37000,
'Jerry': 76000,
'Zero': 120,
}
res = max(iterable, key=lambda x: iterable[x]) # x: 字典的k 返回值:做比较的值
print(res)
iterable = {
'Bob': {'no': 100, 'salary': 12000},
'Tom': {'no': 200, 'salary': 37000},
'Jerry': {'no': 50, 'salary': 76000},
'Zero': {'no': 150, 'salary': 120},
}
res = max(iterable, key=lambda k: iterable[k]['no'])
print(res)
res = max(iterable, key=lambda k: iterable[k]['salary'])
print(res)
# min
iterable = {
'Bob': [100, 12000],
'Tom': [200, 37000],
'Jerry': [50, 76000],
'Zero': [150, 120],
}
res = min(iterable, key=lambda k: iterable[k][1]) # 薪资最小
print(res)
# sorted
res = sorted([1, 3, 4, 2, 5], key=lambda x: x, reverse=True)
print(res)
iterable = {
'Bob': [100, 12000],
'Tom': [200, 37000],
'Jerry': [50, 76000],
'Zero': [150, 120],
}
res = sorted(iterable, key=lambda x: iterable[x][0]) # 按no排序
print(res)
# map:映射
res = map(lambda x: x + 2, [12000, 36000, 27000, 21000, 10000])
print(list(res))
from functools import reduce
# reduce: 合并
res = reduce(lambda f, n: f * n, [1, 2, 3, 4, 5])
print(res)
```
## 内置函数
```python
https://docs.python.org/zh-cn/3.7/library/functions.html#all
# 重点:
# classmethod()
# staticmenthod()
# super()
# object()
# 名称空间
# globals()
# locals()
# 反射
# getattr()
# setattr()
# delattr()
# 名称空间 <=> 可执行字符串
# exec()
# enumerate()
# isintance()
# len()
# max()
# min()
# open()
# range()
# type()
print('-----------------------------------')
'''
# 运算
print(abs(-1)) # 绝对值
print(pow(2, 3, 3)) # 2 ** 3 % 3
print(sum([1, 2, 3])) # 求和
print(divmod(100, 30)) # 100与30形成商与余数
# 集合判断操作
print(all([1, 2, 'abc'])) # 元素全真为真
print(any([1, "", None])) # 元素有真则真
filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5]) # 偶数才能通过过滤
# 原义字符串
print(ascii('
-*..'))
print(repr('
-*..'))
print(r'
-*..')
# 进制
print(10)
print(bin(10))
print(oct(10))
print(hex(10))
# 类型转化
bool()
str()
bytes()
chr()
ord()
range(1, 5) # [1, 2, 3, 4]
'''
def aaa():pass
print(callable(aaa)) # 可调用的
# 可以理解将最外层''去除,形成可执行的对象
s = 'print(123)'
# print(s)
eval(s)
s = '{"a": 1}'
res = eval(s)
print(res['a'])
res = divmod(100, 30) # 100与30形成商与余数
print(res)
res = filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5])
print(list(res))
# 格式化
res = format(97, 'b')
print(res)
# 全局名称空间
print(globals())
def a():
a = 10
b = 20
print(locals())
a()
# hash算法处理
# print(hash([])) # 可变类型不可hash
# print(hash(())) # 不可变可以hash
# import uuid
# print(uuid.uuid4())
'''
t = max(iter, fn) max(iter lambda k: i[k])
temp = None
for k in iter:
res = fn(k)
# res作为比较的条件
# temp存放以res比较得到的最大值
return temp
'''
```