3

我有一个自动化测试,它使用为文件夹创建屏幕截图的功能。该函数被多个截图实例调用。在每次测试运行时,都会创建一个新文件夹,所以我不关心计数器重置。为了反映这些屏幕截图的顺序,我必须想出可以按顺序排序的名称。这是我的解决方案:

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

这对我来说可以。但我一直认为应该有一种更简单的方法来解决这个问题。在那儿?如果单例是唯一的方法,我的代码可以以任何方式优化吗?

4

4 回答 4

4

您在这里尝试做的是模拟一个全局变量。

没有充分的理由这样做。如果您真的想要一个全局变量,请将其明确设为全局变量。

您可以创建一个简单的Counter类,count每次访问它时递增 1,然后创建它的全局实例。但是标准库已经免费为您提供了类似的东西itertools.count,正如 DSM 在评论中解释的那样。

所以:

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 才能访问它。

但是如果你担心,正如你从源代码中看到的那样,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这个问题。

值得指出的是,使用经典类而不是新式类(通过在括号内不传递任何内容)是一个非常糟糕的主意,如果你确实想要一个经典类,你应该关闭括号,大多数 Python 程序员将 nameCounter与 class相关联collections.Counter,没有理由count不能是 a @classmethodor @staticmethod... 在这一点上,这正是 Andrew T. 的答案。正如他所指出的,这比您正在做的事情要简单得多,而且或多或少是 Pythonic。

但实际上,所有这一切并不比仅仅创建_count一个模块级全局并添加一个模块级count()函数来递增和返回它更好。

于 2013-03-15T22:44:34.037 回答
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))
于 2013-03-15T18:23:51.620 回答
1

Using static methods and variables. Not very pythonic, but simpler.

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
于 2013-03-15T18:35:40.610 回答
0

好吧,你可以使用这个解决方案,只要确保你从不初始化 order kwarg!

函数中的 Mutable 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]))
于 2013-03-15T21:56:46.103 回答