Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如果你不';我不能分配它吗?_Python_Performance_List Comprehension - Fatal编程技术网

Python 如果你不';我不能分配它吗?

Python 如果你不';我不能分配它吗?,python,performance,list-comprehension,Python,Performance,List Comprehension,,我正在和一位评论人争论,他认为 for t in threads: t.join() 会比 [t.join() for t in threads] 撇开“滥用理解”的问题不谈——我倾向于同意,但我想用一句话来说明这一点:我的版本(第二个版本)到底有多高效?。Python是否总是/在我的例子中具体化列表理解,还是在内部使用生成器 map(lambda t:t.join(),threads)会更有效吗?或者是否有其他方法将函数应用于列表中的每个元素线程?列表理解将始终生成一个列表对象,

,我正在和一位评论人争论,他认为

for t in threads:
    t.join()
会比

[t.join() for t in threads]

撇开“滥用理解”的问题不谈——我倾向于同意,但我想用一句话来说明这一点:我的版本(第二个版本)到底有多高效?。Python是否总是/在我的例子中具体化列表理解,还是在内部使用生成器

map(lambda t:t.join(),threads)
会更有效吗?或者是否有其他方法将函数应用于列表中的每个元素
线程

列表理解将始终生成一个列表对象,在这种情况下,所有
t.join()
调用的返回值。因此,Python会为您生成带有
None
长度
len(threads)
值的as列表。Python永远不会尝试优化列表对象的创建

当您使用
lambda
添加额外的堆栈推送时,使用
map()。只需使用显式
for
循环即可

实际上,对于一系列线程连接,在这里尝试微优化是没有意义的。 您正在损害一段非关键代码的可读性

换句话说,我完全同意评论者的看法。不要仅仅为了副作用而使用列表理解或
map()
,这样你就不用按ENTER键并创建两行代码了

引述:

  • 可读性很重要

如果您希望为此使用一行程序,请编写一个排气函数,并将其与生成器表达式结合使用:

def exhaust(iterator):
    for _ in iterator:
        pass

exhaust(t.join() for t in threads)
那么您就不必为所有列表存储支付费用

请随意重命名
排气
一些更简洁或与您的使用相关的名称


我已经看到这个列表理解滥用了很多,甚至在面试编码样本中,我们已经明确指示应聘者在解决问题时避免无限的内存增长。

如果你想要一行代码,为什么不在线程中对t执行
:t.join()


对我来说,这似乎是最简单的解决方案,也可能是最快的解决方案(尽管事实上,连接线程的开销很可能会使其他任何事情相形见绌)

您可以制作一个按需工作的foreach。我建议不要这样做,因为这不是一种正常的python方式。未经测试,但大致如下:

class foreach:
    def __init__(self, object_list):
        self.__object_list = object_list

    def __getattr__(self, name):
        def f(*args, **kwargs):
            for obj in self.__object_list:
                getattr(obj, name)(*args, **kwargs)
        return f


foreach(thread_list).join()
它几乎创建了一种代理对象,它将带有任何参数的任何调用转发给所有对象


(如果您愿意在我的开发团队中这样做,我很可能会与您进行一次很好的交谈,但这确实是python中可能的一个例子)

一种情况,在这种情况下,没有赋值列表压缩优于
,因为
循环是在赋值
self
或类似于
locals().items()

列表压缩有自己的作用域,并对常规循环执行相同的操作,如下所示:

for k, v in locals().items():
    if k != 'self':
        setattr(self, k, v)
[self.__setattr__(k, v) for k, v in locals().items() if k in self.cls.__slots__]
将同时分配
k
v
,因为它们是在第一个循环之后添加到
locals()
的。尽管我更喜欢将其与
\uuuuu插槽\uuuuu
结合使用,如下所示:

for k, v in locals().items():
    if k != 'self':
        setattr(self, k, v)
[self.__setattr__(k, v) for k, v in locals().items() if k in self.cls.__slots__]

其中
self.cls
type(self)
self.\uuuu class\uuuuu
,在这种情况下,两者都需要相等的
if
语句,但即使在这种情况下,我仍然更喜欢列表压缩。

如果是低效的,您的意思是说它需要多长时间才能完成完整的操作,或者每个场景需要多少资源?因为,使用
.tick()
函数或简单地使用
time.time()
在速度方面区分这两种操作非常容易。除此之外,我的大脑告诉我,第二种解决方案的执行时间要比两行程序长。“我想要一行程序。”。因此,删除线程中t的换行符:
:t.join()
。如果可读性较差,那么一行代码的可读性较差,您不应该需要一行代码。所以,努力治愈自己对一行程序的渴望:-)@Torxed:我想知道我是否可以避免内存开销。@SteveJessop:我只是觉得奇怪,我不能说
foreach(threads)。join()
或其他什么:-)@Aarondigula你真的可以这么做,如果使foreach返回一个代理对象,其中_getattr__生成了调用包装项上的命名方法的函数。但你可能不应该<代码>排气
也可以写入集合.deque(iterable,maxlen=0)
。我不确定这是否会将循环推到C代码中,但这是允许的,这就是
itertools
recipes推荐的。可爱!虽然可能有点迟钝,但为什么发电机那么“聪明”?只要使用一个常规循环,不要试图混淆任何阅读代码的人。好吧,我同意你的观点-我只是回答了“我想要一个一行程序”部分。好吧,如果它达到了真正的结果,任何人都会提前返回。因此它适用于t.join(),它总是不返回任何值,但它非常微妙——人们很容易在其他地方尝试这个习惯用法,当它失败时会感到惊讶。你是说函数调用的运行时开销吗?我认为这与t.join()的成本相比微不足道。(所有这些都是相当学术性的——你应该只做for循环。)虽然这会起作用,但我仍然在寻找一个可读的解决方案。比如
foreach(threads).join()
之类的。我的感觉是我忽略了一些显而易见的东西。我可以想出一种方法来创建一个函数
foreach
,它的工作原理与您编写的完全相同,但我想我会把它留给自己,并重复这个主题:让您的代码对其他Python用户可读。+1我同意您的观点,我只是想确定我没有忽略什么。我不能说
all(threads)。join()
或其他什么如果你想让它这样读,就写一个名为
join\u all\u threads的函数