Python 迭代器 生成器 装饰器 上下文管理器
基本约定
ClsX: 类X
Valx: 变量x
Funcx: 函数x
Codex: 代码片段x
Python内部对象特殊方法/属性
1.__dict__属性:
ClsA.__dict__,类A的属性字典,包括
属性,https://www.cnblogs.com/alvin2010/p/9102344.html
ValA.__dict__, 变量X的属性字典
2.__getattr__(self, item):
# 获取名为item的属性
# 默认等同于:return self.__dict__[item]
3.__setattr__(self, item, value):
# 设置名为item的属性值为value
# 默认等同于:self.__dict__[item] = value
迭代器和生成器
迭代是Python中遍历访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。
https://www.runoob.com/python...
# 假设有个方法,可以根据传入的ID,从服务器获取内容,返回为空的时候说明没有内容了
def get_data(rid):
if rid > 5:
return
return '数据%s' % rid
def get_data2(rid):
if rid > 3:
return
return 'Data%s' % rid
# 现在我们需要遍历全部数据
i = 1
while True:
data = get_data(i)
if not data:
break
print(data)
i += 1
i = 1
while True:
data = get_data2(i)
if not data:
break
print(data)
i += 1
# 封装版本
def get_all(func):
datas = []
i = 1
while True:
data = func(i)
if not data:
break
datas.append(data)
i += 1
return datas
for data in get_all(get_data):
print(data)
# 生成器版本
def gen_all(func):
i = 1
while True:
data = func(i)
if not data:
break
yield data
i += 1
for data in gen_all(func=get_data):
print(data)
# 迭代器版本
class AllGetter:
def __init__(self, func):
self.func = func
self.i = 1
def __iter__(self):
return self
def __next__(self):
data = self.func(self.i)
if not data:
raise StopIteration
self.i += 1
return data
x = (i for i in [1,2,3])
while True:
print(x.__next__())
for data in AllGetter(func=get_data):
print(data)
x = AllGetter(func=get_data)
for data in x:
print(data)
#等同于
it = iter(x) # it = x.__iter__()
while True:
print(next(it))
装饰器
# 假如我们需要统计某些函数func1、func2的执行时间
import time
def func1():
time.sleep(1)
def func2():
time.sleep(2)
t1 = time.time()
func1()
print('func1', time.time() - t1)
t2 = time.time()
func2()
print('func2', time.time() - t2)
# 这类问题可抽象为以下:
# Code1
# FuncX
# Code2
def func3(a, b):
print('a+b', a+b)
# 定义函数的做法
def timeit(func, *args, **kwargs):
t = time.time()
func(*args, **kwargs)
print(func.__name__, time.time() - t)
timeit(func1)
timeit(func2)
timeit(func3, 1,2)
def funcwrap(rawfunc):
def _wrap(newfunc):
newfunc.__name__ = rawfunc.__name__
return newfunc
return _wrap
# 装饰器写法
def timeit2(func):
from functools import wraps
def _func(*args, **kwargs):
t = time.time()
r = func(*args, **kwargs)
print(func.__name__, time.time() - t)
return r
return _func
@timeit2
def func4():
time.sleep(0.5)
# 装饰器左右类似
newfunc4 = timeit2(func4)
func4 = newfunc4
func4(1,2)
# 装饰器用于类
clzs = []
def addit(clz):
clzs.append(clz)
return clz
@addit
class A(object):
pass
@addit
class B(object):
pass
@addit
class C(object):
pass
print(clzs)
# 带参数的装饰器
def asapi(logined):
def _wrap(func):
def _func(*args, **kwargs):
if logined:
print('err')
return
r = func(*args, **kwargs)
return r
return _func
return _wrap
@asapi(logined=True)
def fun6():
print('xxx')
# 等同于
logined = asapi(logined=True)
@logined
def fun6():
print('xxx')
上下文管理器
# 某些情况下,我们需要统计某段代码的执行时间
# 这类问题可抽象为以下:
# Code1
# CodeX
# Code2
import time
def func1():
x = 2
# 我们要统计下面这三行代码的执行时间
a = 1
b = a + x
x = 4
# 一般做法
def func1():
x = 2
st = time.time()
a = 1
b = a + x
x = 4
print('cost time', time.time()-st)
# 上下文管理做法
class TimeIt(object):
def __enter__(self):
self.start = time.time()
def __exit__(self, exc_type, exc_val, exc_tb):
print('time cost', time.time()-self.start)
def func1():
x = 2
with TimeIt():
a = 1
b = a + x
x = 4
# 等同于
def func1():
x = 2
ti = TimeIt()
ti.__enter__()
a = 1
b = a + x
x = 4
ti.__exit__(None,None,None)
# 和上下文环境进行交互
class TimeIt2(object):
def __enter__(self):
self.start = time.time()
self._marks = []
return self
def __exit__(self, exc_type, exc_val, exc_tb):
for n, t in self._marks:
print(n, t-self.start)
print('time cost', time.time()-self.start)
def mark(self, name):
print('->', name, time.time() - self.start)
self._marks.append((name, time.time()))
with TimeIt2() as t:
time.sleep(2)
t.mark('T1')
time.sleep(1)
t.mark('T2')
time.sleep(0.5)
# 等同于
ti = TimeIt2()
t = ti.__enter__()
time.sleep(2)
t.mark('T1')
time.sleep(1)
t.mark('T2')
time.sleep(0.5)
ti.__exit__(None,None,None)
# 上下文交互2
class SendContext(object):
def __init__(self, tag):
self.tag = tag
def __enter__(self):
self.msglist = []
return self.send
def __exit__(self, exc_type, exc_val, exc_tb):
print(self.msglist)
def send(self, userid):
self.msglist.append(userid)
with SendContext('order') as send:
for o in [1,2,3,4]:
send(1)
3.9k 声望
36 粉丝
推荐阅读
macOS上HBuildX 开发 uni-app项目,运行调试时编辑保存文件不会自动编译更新页面
点击运行到"Chrome",HBuildX能够正常编译并打开浏览器正常显示网页,这个时候如果去修改代码并保存,HBuildX底部控制台并不会出现重新编译的字样(正常是有的),浏览器也不会自动刷新,同时手动刷新变动的内容...
RobinTang阅读 763
日常Python 代码片段整理
1、简单的 HTTP Web 服务器 {代码...} 2、单行循环List {代码...} 3、更新字典 {代码...} 4、拆分多行字符串 {代码...} 5、跟踪列表中元素的频率 {代码...} 6、不使用 Pandas 读取 CSV 文件 {代码...} 7、将列表...
墨城赞 2阅读 282
Unicode 正则表达式(qbit)
前言本文根据《精通正则表达式》和 Unicode Regular Expressions 整理。本文的示例默认以 Python3 为实现语言,用到 Python3 的 re 模块或 regex 库。基本的 Unicode 属性分类 {代码...} 基本的 Unicode 子属性Le...
qbit阅读 4.3k
Python + Sqlalchemy 对数据库的批量插入或更新(Upsert)
由于不同数据库对这种 upsert 的实现机制不同,Sqlalchemy 也就不再试图做一致性的封装了,而是提供了各自的方言 API,具体到 Mysql,就是给 insert statement ,增加了 on_duplicate_key_update 方法。
songofhawk赞 1阅读 1.9k评论 4
Go for 循环有时候真的很坑。。。
大家好,我是煎鱼。不知道有多少 Go 的面试题和泄露,都和 for 循环有关。今天我在周末认真一看,发现了 redefining for loop variable semantics 。著名的硬核大佬 Russ Cox 表示他一直在研究这个问题,并表示十...
煎鱼阅读 3.4k
打脸了兄弟们,Go1.20 arena 来了!
大家好,我是煎鱼。大概半年前,我写过一篇文章《Go 要违背初心吗?新提案:手动管理内存》。有兴趣了深入解的同学,可以再回顾一下。当时我们还想着 Go 团队应该不会接纳,至少不会那么快:懒得翻也可以看我再次...
煎鱼阅读 3.1k
docker 打包 selenium+chromedriver+chrome 遇到的坑和解决方案
docker 跑 selenium 的时候遇到了很多坑,记录一下排坑过程Python 使用 selenium+chromedriver+chrome 实现网页截图Dockerfile {代码...} 让我们一行一行来看RUN (echo "deb http://mirrors.aliyun.com/debi...
ponponon阅读 1.9k
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。