用枚举定义 python 类

Posted

技术标签:

【中文标题】用枚举定义 python 类【英文标题】:Defining python classes with enums 【发布时间】:2015-09-03 18:23:07 【问题描述】:

最近我定义了一个 Python 类,如下所示。

from datetime import datetime, date, time
import enums


class ExampleClass:

    defaults = (-1, "", "", datetime.today(), "", -1, [], "", -1, "", "", [], "")

    def __init__(self, **kwargs):
        count = 0
        for ex in enums.ExampleEnums:
            setattr(self, ex.name, kwargs.get(ex.value, ExampleClass.defaults[count]))
            count += 1

    def __str__(self):
        return_string = "Example Object with "
        count = 0
        for val in enums.ExampleEnums:
            if (getattr(self, val.name) != ExampleClass.defaults[count]):
                return_string += str("%s: %s, " % (val.name, getattr(self, val.name)))
            count += 1
        return return_string[:-2]

    def __repr__(self):
        return_string = ""
        count = 0
        for val in enums.ExampleEnums:
            if (getattr(self, val.name) != ExampleClass.defaults[count]):
                return_string += str("%s=%s, " % (val.value, getattr(self, val.name)))
            count += 1
        return return_string[:-2]

    def __eq__(self, other):
        for val in enums.ExampleEnums:
            if (getattr(self, val.name) != getattr(other, val.name)):
                return False
        return True

    def __ne__(self, other):
        for val in enums.ExampleEnums:
            if (getattr(self, val.name) == getattr(other, val.name)):
                return False
        return True

无论如何,我想知道:这是为数据类编写类定义的好方法吗?有什么方法可以改进吗?我不需要任何代码,只需要概括性就可以了,因为我只是将其发布为了解如何提高自己在 Python 中的编码能力的一种方式。

谢谢

【问题讨论】:

很高兴我的建议受到好评,但请不要编辑您问题中的原始代码(请参阅What you may and may not do after receiving answers)。 @mkrieger1 - 那篇文章是专门针对代码审查的,而 Stack Overflow 有不同的系统。 @rolfl 哦,我刚刚看到了。但是相同的(或至少相似的)原则是否适用于这里? 实际上,这整个问题不是更适合代码审查而不是堆栈溢出吗? 令我震惊的是,这整个问题都是题外话,因为没有具体的编程问题......而且,整个问题应该在代码审查中提出,但是,尽管如此,不,同样的原则在这里并不适用——尽管我经常认为它们应该适用。 【参考方案1】:

你可以在函数__ne__中调用self._eq__(other)

【讨论】:

我喜欢。我会做到的,但那是 Pythonic 吗?只是好奇【参考方案2】:

你多次使用这个模式(这里显示的是__init__,它也适用于__str____repr__):

count = 0
for ex in enums.ExampleEnums:
    setattr(self, ex.name, kwargs.get(ex.value, ExampleClass.defaults[count]))
    count += 1

最好直接遍历ExampleClass.defaults 中的项目,而不是手动计算索引。这可以使用zip 来实现:

for ex, default in zip(enums.ExampleEnums, ExampleClass.defaults):
    setattr(self, ex.name, kwargs.get(ex.value, default))

__eq__ 方法可以使用all 进行简化:

def __eq__(self, other):
    return all(getattr(self, val.name) == getattr(other, val.name)
               for val in enums.ExampleEnums)

然后,正如其他人已经说过的,您可以将__ne__ 表达为__eq__,甚至使用== 运算符:

def __ne__(self, other):
    return not self == other

【讨论】:

谢谢。我不知道拉链。真的很感激【参考方案3】:

编写数据类的最佳方式因用例而异。但是根据您所提供的内容,您不应该重复代码。一旦你定义了__eq__ 操作符,你应该在别处使用它。 (如果您对__eq__ 的定义发生变化怎么办?)另外,您不必定义太阳下的每一种神奇方法……只要定义对您有价值的东西即可。

查看 Python 魔法方法指南:http://www.rafekettler.com/magicmethods.html

另请参阅 __ne____eq__ 的答案以及如何定义它们:Python implementing ne operator based on eq。

您还应该研究装饰器(特别是 @property)。

【讨论】:

感谢您的回复。如上所述,__ne__ 运算符已更改以反映其与 __eq__ 运算符的对称性。此外,我并没有定义所有这些,只是那些可能对我有用或者我会经常使用到我想明确说明它们的操作的那些。最后,在此之前我使用的是@property,但我并不特别关心它们是私有的,我只是不喜欢一遍又一遍地写出相同的定义。

以上是关于用枚举定义 python 类的主要内容,如果未能解决你的问题,请参考以下文章

Python枚举类定义和使用

Python枚举类

草根学Python枚举类

Python 的枚举 Enum

Python枚举类

Python-枚举