我有一个自动化测试,它使用为文件夹创建屏幕截图的功能。此功能由多个屏幕截图实例调用。在每次测试运行时,都会创建一个新文件夹,所以我不关心计数器重置。为了反映这些屏幕截图的顺序,我必须提出可以按顺序排序的名称。这是我的解决方案:
def make_screenshot_file(file_name):
order = Counter().count
test_suites_path = _make_job_directory()
return make_writable_file(os.path.join(test_suites_path,'screenshot',file_name % order))
class Counter():
__counter_instance = None
def __init__(self):
if Counter.__counter_instance is None:
self.count = 1
Counter.__counter_instance = self
else:
Counter.__counter_instance.count += 1
self.count = Counter.__counter_instance.count
对我来说很好。但我一直认为应该有一种更简单的方法来解决这个问题。在那儿?如果单身是唯一的方式,我的代码可以以任何方式进行优化吗?
答案 0 :(得分:4)
你在这里要做的是模拟一个全局变量。
没有充分的理由这样做。如果你真的想要一个全局变量,那么明确地将它变成一个全局变量。
您可以创建一个简单的Counter
类,每次访问时将count
递增1,然后创建它的全局实例。但正如DSM在评论中解释的那样,标准库已经在itertools.count
中免费提供了类似的内容。
所以:
import itertools
_counter = itertools.count()
def make_screenshot_file(file_name):
order = next(_counter)
test_suites_path = _make_job_directory()
return make_writable_file(os.path.join(test_suites_path,'screenshot',file_name % order))
我不确定为什么你会担心这会占用多少存储空间或时间,因为我无法设想任何程序,无论你是使用8个字节还是800个单个对象都可能无关紧要你可能永远不会有一个以上,或者当你只做了几次时它是否需要3ns或3us才能访问它。
但如果您 担心,正如您从the source所看到的那样,count
是用C实现的,它的内存效率非常高,如果你不这样做的话任何与它相关的东西,基本上只有一个PyNumber_Add
来生成每个数字,这比解释几行代码要少得多。
由于您的问题,以下是使用_count
类属性而不是__counter_instance
类属性从根本上简化现有代码的方法:
class Counter():
_count = 0
def count(self):
Counter._count += 1
return Counter.count
当然现在你必须Counter().count()
而不仅仅是Counter().count
- 但如果重要的话,你可以用@property
来解决这个问题。
值得指出的是,使用经典类而不是新式类(通过在parens中传递任何内容)是一个非常糟糕的主意,如果你做想要一个经典类你应该让parens关闭,大多数Python程序员会将名称Counter
与类collections.Counter
相关联,并且没有理由count
不能是@classmethod
或{{ 1}} ......在这一点上,这正是Andrew T.的答案。正如他所指出的那样,这比你正在做的更简单,而且不会更多或更少的Pythonic。
但实际上,所有这些并不仅仅是让@staticmethod
成为模块级全局,并添加一个模块级_count
函数,该函数会递增并返回它。
答案 1 :(得分:2)
为什么不做呢
order = time.time()
或做类似
的事情import glob #glob is used for unix like path expansion
order = len(glob.glob(os.path.join(test_suites_path,"screenshot","%s*"%filename))
答案 2 :(得分:1)
使用静态方法和变量。不是pythonic,但更简单。
def make_screenshot_file(file_name):
order = Counter.count() #Note the move of the parens
test_suites_path = _make_job_directory()
return make_writable_file(os.path.join(test_suites_path,'screenshot',file_name % order))
class Counter():
count_n = 0
@staticmethod
def count():
Counter.count_n += 1
return Counter.count_n
print Counter.count()
print Counter.count()
print Counter.count()
print Counter.count()
print Counter.count()
atarzwell@freeman:~/src$ python so.py
1
2
3
4
5
答案 3 :(得分:0)
好吧,您可以使用此解决方案,只需确保您永远不会初始化订单kwarg!
函数中的可变Kwargs像类全局变量一样工作。正如您最初可能想到的那样,值不会在调用之间重置为默认值!
def make_screenshot_file(file_name , order=[0]):
order[0] = order[0] + 1
test_suites_path = _make_job_directory()
return make_writable_file(os.path.join(test_suites_path,'screenshot',file_name % order[0]))