【问题标题】:Proper use of class constants in Python在 Python 中正确使用类常量
【发布时间】:2014-04-09 13:29:59
【问题描述】:

这个问题具体涉及到下面示例代码中类常量ABOVEBELOW的使用。

我在不同的模块中有几个不同的类,如下所示:

class MyClass(object):
    ABOVE = 1
    BELOW = 0

    def __init__(self):
        self.my_numbers = [1,2,3,4,5]

    def find_thing_in_direction(self, direction, cutoff):
        if direction == self.ABOVE:
            return [n for n in self.my_numbers if n > cutoff]
        else:
            return [n for n in self.my_numbers if n < cutoff]


my_class = MyClass()
my_var = my_class.find_thing_in_direction(MyClass.ABOVE, 3)

如果我有一些分散在不同模块中的类,每个模块都有自己的 ABOVEBELOW,我应该将这些常量提取到某个地方,还是将常量保留在自己的类中更好?

有没有更 Pythonic 的方式来代替使用这些类常量?

【问题讨论】:

  • 版主:我最初在 Code Review 上发布了这篇文章,因为离题而被关闭。我在 Programmers SE 聊天室询问它是否是程序员的主题,有人建议在这里会更好。如果它不适合 stackoverflow,您能否建议哪个 SE 站点最好?
  • 如果 ABOVE 或 BELOW 的值发生变化,您是否希望所有值同时变化?
  • 顺便说一句,你那里的if 块毫无意义:)
  • @unutbu 我想答案是如果 ABOVE 或 BELOW 发生变化,我希望行为保持不变。也就是说,我希望如果使用 direction=ABOVE 调用代码,则无论 ABOVE 的值如何,都会执行第一个 if 语句
  • @ErikAllik 已修复谢谢 :-)

标签: python constants


【解决方案1】:

您似乎正在使用类作为常量的命名空间。您应该问问自己,每个类中的 ABOVEBELOW 常量是否彼此之间存在差异。

如果需要区分(不仅是数字差异,还有语义差异),那么将它们存储在它们所代表的类中是最好的方法。另一方面,如果它们在每个类中都具有相同的语义,那么您就没有坚持 DRY 原则并且您正在复制代码。

解决方案可以将它们存储在模块级别,也可以创建一个仅包含常量的类。

【讨论】:

  • 顺便说一句:创建一个包含常量的类是不是 Pythonic...这是Java 所做的,因为您不能将东西放在类之外。在 Python 中,你把它放在一个模块中,如果你想以命名空间的方式引用它们,你导入模块,然后用constants.FOO 而不是FOO
  • @ErikAllik 我同意你的看法,如果你仔细阅读,这是我的第一个建议,但是一些来自其他语言的人觉得这很难理解,而且,对于一些复杂的项目树,它可能很方便去做(从组织的角度来看)。
  • 只是想确保人们知道这一点:)
【解决方案2】:

编辑:

根据 OP 的评论,我意识到我忽略了这样一个事实:ABOVEBELOW 并不是真正的参数常量,而只是强类型名称(即枚举)。

因此我认为接受的答案是正确的:)

旧答案:

如果常量的数量很少,这真的归结为偏好,但是,如果你有很多常量,那么按类命名空间可能是个好主意。

另外,你有继承吗?如果是,您是否覆盖子类中的常量值?如果是,您显然需要将它们保留在您的课程中。

另外,my_class.find_thing_in_direction(MyClass.ABOVE, 3) 很臭:find_thing_in_direction 很可能应该直接引用它自己的类'ABOVE 常量。

另外,SomeClass 是一个非常糟糕的类名:)

【讨论】:

  • 你能澄清你的意思find_thing_in_direction应该最有可能直接引用它自己的类'ABOVE常量吗?你的意思是我应该使用self.ABOVE 而不是MyClass.ABOVE?此外,如果我将它们放在模块中,我想表明用户应该查看文件中完全其他的位置以获取有效值。最好的方法是只写“通过 MyModule.ABOVE 或 MyModule.BELOW 作为方向”还是您推荐其他内容?
【解决方案3】:

对于您的特定方法find_thing_in_directiondirection 参数最好是一个bool 标志,命名为reverse,就像内置sorted 函数所做的那样:

def find_thing_in_direction(self, reverse, cutoff):
  if not reverse:
    pass
  else:
    pass

这样你就不必使用类属性了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-24
    • 1970-01-01
    • 2012-03-11
    • 1970-01-01
    • 2013-09-13
    • 1970-01-01
    相关资源
    最近更新 更多