python - 从python3中具有多个属性的对象列表中提取多个属性列表
问题描述
我有一个A
包含多个字段a
的类b
,,,c
。我有一个此类对象的列表A
。现在,我想提取 3 个列表,第一个包含a
来自所有对象的 field 的值,第二个包含 fieldb
的值和第三个c
的值的列表。
我找到了以下答案
这个答案说我可以使用如下列表理解
a_list=[obj.a for obj in obj_list]
a_list=(obj.a for obj in obj_list)
现在,我的问题是当我想提取多个属性时这会起作用吗?如果我如下写 3 次该行
a_list=(obj.a for obj in obj_list)
b_list=(obj.b for obj in obj_list)
c_list=(obj.c for obj in obj_list)
我将遍历列表 3 次。不会很贵吗?在这种情况下,使用 for 循环会更好吗?
for obj in obj_list:
a_list.append(obj.a)
b_list.append(obj.b)
c_list.append(obj.c)
哪个更快?这是一个更好的方法。还有其他更好的优化方式吗?谢谢!
解决方案
每当您认为“ X比Y快”时,您都需要进行测量。
您可以设计一种不通过您的列表三次的方法。
这种“方式”可能仍然不会更快,因为它使整个代码更加复杂并且计算成本更高。
不通过对象 trice 列表的一种方法是利用 zip 和 map,如下所示:
class O:
def __init__(self,a,b,c):
self.a=a
self.b=b
self.c=c
def __str__(self):
return f"#{self.a} {self.b} {self.c}#"
def __repr__(self): return str(self)
obj = [O(a,a**4,1.0/a) for a in range(2,20)]
print(obj)
# use a generator to make 3-tuples of your classes attributes and decompose
# those into zip which builds your lists
a,b,c = map(list, zip( *((e.a,e.b,e.c) for e in obj)) )
print(a,b,c )
对象:
[#2 16 0.5#, #3 81 0.3333333333333333#, #4 256 0.25#, #5 625 0.2#,
#6 1296 0.16666666666666666#, #7 2401 0.14285714285714285#, #8 4096 0.125#,
#9 6561 0.1111111111111111#, #10 10000 0.1#, #11 14641 0.09090909090909091#,
#12 20736 0.08333333333333333#, #13 28561 0.07692307692307693#,
#14 38416 0.07142857142857142#, #15 50625 0.06666666666666667#,
#16 65536 0.0625#, #17 83521 0.058823529411764705#,
#18 104976 0.05555555555555555#, #19 130321 0.05263157894736842#]
结果:
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[16, 81, 256, 625, 1296, 2401, 4096, 6561, 10000, 14641, 20736, 28561,
38416, 50625, 65536, 83521, 104976, 130321]
[0.5, 0.3333333333333333, 0.25, 0.2, 0.16666666666666666, 0.14285714285714285,
0.125, 0.1111111111111111, 0.1, 0.09090909090909091, 0.08333333333333333,
0.07692307692307693, 0.07142857142857142, 0.06666666666666667, 0.0625,
0.058823529411764705, 0.05555555555555555, 0.05263157894736842]
您仍然需要测量是否比遍历对象列表更快。
即使对于 18 个元素它会更慢,但对于 200 万个元素可能会更快。因此,使用什么是高度间接的。
时间:
s = """
class O:
def __init__(self,a,b,c):
self.a=a
self.b=b
self.c=c
def __str__(self):
return f"#{self.a} {self.b} {self.c}#"
def __repr__(self): return str(self)
# changed to ** 2 instead of 4
# changed to 200 elements
obj = [O(a,a**2,1.0/a) for a in range(2,200)]
"""
code1="""
a,b,c = map(list,zip( *((e.a,e.b,e.c) for e in obj)) )
"""
code2="""
a1 = [e.a for e in obj]
b1 = [e.b for e in obj]
c1 = [e.c for e in obj]
"""
from timeit import timeit
print(timeit(code1,setup=s,number=100000))
print(timeit(code2,setup=s,number=100000))
结果:
7.969175090000135 # map + zip
5.124133489000087 # simple loop
推荐阅读
- python-3.x - 无法使用核心 tensorflow api 为张量“Placeholder_1:0”提供形状 (242,) 的值
- xamarin.android - 如何在 Visual Studio 2019 中定位 Android 4.1?
- ios - 获取 imagePaths 的所有资产
- javascript - 向站点添加了一些代码,它可以正常工作,但似乎无限滚动到页脚之外
- php - 使用 POSTMAN 测试 Laravel API 路由
- c# - 如何在 C# 中使用 Process.Start 传递 argv[0]
- c# - 具有相同类和相同类列表的 C# 泛型
- rust - 如何在 Rust 中获取进位标志的值
- jquery - 从远程 url 使用 JSON 创建 Dyantable
- firebase - 列表的 MapView.Markers 未在渲染时显示