在类内部访问常量全局范围变量的Python方法?

时间:2019-01-12 02:02:45

标签: python

说我有以下代码:

@SpringBootApplication
public class RedglassCoreApplication {
            
  public static void main(String[] args) {
    SpringApplication.run(RedglassCoreApplication.class, args);
  }
  
  @Bean
  public DataSource dataSource() {
    return //DataSource Instance
  }
}

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

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() 类的total方法内部是否有更多的Python方式访问collectedrun?保证Check的值不变。据我所知,我无法将其他任何内容传递给total方法。将相同的runtotal值传递给collected类的构造函数似乎很愚蠢,但这也许是最佳实践吗?

3 个答案:

答案 0 :(得分:3)

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))

没有global,没有线程和更少的代码行。

答案 1 :(得分:0)

如果您完全确定自己将始终在函数中使用相同的全局变量,并且全局变量永远不会改变,那么就无需使用参数。

最Python的方法是使用total关键字明确指定collectedglobal是全局变量:

def run(self):
    global total
    global collected

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

答案 2 :(得分:0)

我在代码中添加了一个锁,这是一种实现方法。

collectedtotal是类变量,并且由于它是共享状态,因此最好用锁来保护它。请注意,将实例变量设为lock会达到目的,因此它是一个类变量。

import threading

class Check(threading.Thread):
    collected = []
    total = 0
    lock = threading.Lock()
    def __init__(self, item):
        super(Check, self).__init__()
        self._item = item

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

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

print (Check.total)
print (Check.collected)