【问题标题】:Pythonic way around Enums [closed]围绕枚举的 Pythonic 方式 [关闭]
【发布时间】:2016-10-13 18:35:46
【问题描述】:

pythonic 告诉函数调用者给定参数支持什么值的方法是什么?

他是 PyQt(用于 GUI)的一个例子。假设我有一个复选框,

class checkbox(object):
    ....
    def setCheckState(self, value):
        ....

这里,setCheckState() 应该只期望选中未选中

PyQt 使用内置枚举(即Qt.CheckedQt.Unchecked),但这很糟糕。我一直在文档中寻找我正在使用的对象的枚举。

显然 PyQt 是用 unpythonic C++ 风格编写的。 应该在 Python 中如何处理这个或类似的问题?根据PEP 435 的说法,枚举似乎是该语言和非常具体的应用程序的最新添加,所以我认为有/有更好的方法来处理这个?

我想让我编写的代码在我的函数需要特定参数值时易于使用——几乎就像函数的组合框。

【问题讨论】:

  • 枚举的引入正是因为每个人都在使用自己的 hacky 替代品。如果您想要的是枚举,请使用枚举。如果您只有两种状态,请考虑使用布尔值:def setCheckState(self, checked=True):
  • 控制反转的支持者会争辩说,应该有三个不采用 any 参数的独立函数:checkbox.set_checked()checkbox.set_unchecked() 和 @987654329 @.
  • 我想这比我想象的更基于意见,我希望像 Python 中的大多数东西一样,有一个正确的方法来做。
  • @chepner 你能解释一下set_checkedset_uncheckedset_checked_state(bool) 之间的区别吗?或者例如is_checked财产...
  • @zvone 至少,它完全回避了应该使用什么值来指示哪个状态的问题。如果要选中该框,则不必担心是否应该将1True"on""checked"SOME_CONSTANT 作为参数传递;您只需调用非常明显的set_checked() 函数。

标签: python python-2.7 function parameters enums


【解决方案1】:

One Obvious Way是函数注释。

class CheckBox(enum.Enum):
    Off = 0
    On = 1

def setCheckState(self, value: CheckBox):
    ...

这很清楚地表明value 应该是CheckBox 的一个实例。拥有Enum 只会让这件事变得更容易一些。

不过,注释本身在 2.7 中并不直接得到支持。常见的解决方法包括将该信息放入函数文档字符串(各种工具可以找到它)或 cmets(我们已经知道)。

如果为自己的代码寻找方法:使用注解装饰器。这样做的好处是3+可以继续工作:

class annotate(object):
    def __init__(self, **kwds):
        self.kwds = kwds
    def __call__(self, func):
        func.__annotations__ = self.kwds

@annotate(value=CheckBox)
def setCheckState(self, value):
    ...

要成为一个健壮的装饰器,它应该检查kwds 的内容是否与函数参数名称匹配。

【讨论】:

  • 函数注解在 Python 2.7 中不可用。
  • 这可以解释为什么我以前没有听说过它们。
  • 啊,我错过了 2.7 标签,对不起。
  • 供参考,PEP 3107 是关于函数注释的文档。反正我现在正在通读。
【解决方案2】:

这样就可以了

import collections

def create_enum(container, start_num, *enum_words):
    return collections.namedtuple(container, enum_words)(*range(start_num, start_num + len(enum_words)))

Switch = create_enum('enums', 1, 'On', 'Off')

Switch 是你的枚举:

In [20]: Switch.On
Out[20]: 1

In [21]: Switch.Off
Out[21]: 2

好的,我的方法有误 - 我将表示与价值混为一谈。

不过,如果您想枚举更大的范围 - 在我的 fake 方法中,您不必手动添加值。当然,如果你有序列号。

我讨厌额外的打字:-)

【讨论】:

  • Python 现在有Enum,不需要再造假了。
  • @EthanFurman,不幸的是,使用枚举创建的 Switch.Off 和 Switch on 的值不是 0 和 1 - 它们是类型,您需要进一步取消引用才能获得 0 和 1。
  • 如果您使用enum.IntEnum,则不会。
  • @EthanFurman,明白了。我实际上不使用枚举 - 我只是重新修补了我用来为常量创建包装器对象的方法。
  • 您可能想查看aenum。除了高级枚举之外,它还具有 NamedConstant 和基于元类的 NamedTuple。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-06
  • 2016-11-17
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
相关资源
最近更新 更多