首页 > 解决方案 > 访问类内常量全局范围变量的 Pythonic 方式?

问题描述

假设我有以下代码:

import threading

class Check(threading.Thread):
    def __init__(self, item):
        super(Check, self).__init__()
        self._item = item

    def run(self):
        data = '{} ({} total)'.format(self._item, total)
        collected.append(data)

items = ['item{}'.format(i) for i in xrange(5)]
total = len(items)
collected = []
for item in items: Check(item).start()

(让我们抛开上面代码的无用。它的唯一目的是帮助解释问题。)

有没有更 Pythonic 的方式来访问totalcollected从类的run方法内部访问Check?的值total保证不会改变。run据我所知,我无法将任何其他内容传递给该方法。将相同的totalcollected值传递给Check类的构造函数似乎很愚蠢,但也许这是最佳实践?

标签: python

解决方案


global线程不是一个很好的组合。至少,如果你正在改变共享状态,你应该有锁,global这是你可以拥有的“共享”状态的最极端情况。

我绝对建议将两者都传递itemtotal你的Check类,然后从你的线程中检索值并稍后“组装”它:

import threading

class Check(threading.Thread):
    def __init__(self, item, total):
        super(Check, self).__init__()
        self._item = item
        self._total = total
        self.result = None

    def run(self):
        data = '{} ({} total)'.format(self._item, self._total)
        self.result = data

 items = ['item{}'.format(i) for i in xrange(5)]
 total = len(items)
 collected = []

 checks = [Check(item) for item in items]
 for check in checks:
     check.start()
 for check in checks:
     check.join()
 collected = [check.result for check in checks]

但是如果你可以使用 Python 3,一个更好的方法是避免子类Thread化并首先直接处理它们:

 from concurrent.futures import ThreadPoolExecutor

 def do_check(item, total):
     data = '{} ({} total)'.format(self._item, self._total)
     return data

 items = ['item{}'.format(i) for i in range(5)]
 total = len(items)

 tpe = ThreadPoolExecutor(max_workers=5)
 collected = list(tpe.map(lambda item: do_check(item, total), items))

没有globals,没有线程,代码行数更少。


推荐阅读