【问题标题】:Enum with functions?带函数的枚举?
【发布时间】:2013-10-23 13:21:16
【问题描述】:

我看到了页面:

我熟悉 this SO question 在 Python 中创建枚举。但是,我在任何地方都找不到具有函数的枚举示例。

我主要是一名 Java 程序员。 我用 Java 写了这段代码:

public enum Role {
    SOLDIER(4),
    DEMOMAN(2),
    SCOUT(4),
    MEDIC(2);

    private final int maxPlayers;

    private Role(int maxPlayers) {
        this.maxPlayers = maxPlayers;
    }

    public int getMaxPlayers() {  return maxPlayers; }
}

我尝试在 Python 中做同样的事情:

class Klass:
    SCOUT = 1
    SOLDIER = 2
    DEMOMAN = 3
    MEDIC = 4

    @staticmethod
    def maxPlayers(klass):
        return {
            Klass.SCOUT : 4,
            Klass.SOLDIER : 4,
            Klass.DEMOMAN : 2,
            Klass.MEDIC : 2,
        }[klass]

出于某种原因。我觉得我做错了。 在 Python 中将函数与枚举关联的最佳做法是什么?

我实际上并不关心建议的答案是否不使用枚举;我只是想了解在 Python 中实现上述 Java 代码的最佳实践。

我愿意在下面使用这个枚举:

class Players(dict):
    def countKlass(self, klass):
        count = len(filter(lambda x: x == klass, self.values()))
        return count

【问题讨论】:

  • 你的Java代码不是纯枚举;它是枚举的子类。如果您只是更改 Klass 使其从 Enum (链接中提到的 PEP 435 枚举)子类化,它应该完全按照您的预期工作。它们是整数,因此查找字典似乎很简单。
  • 这可能会有所帮助:stackoverflow.com/questions/36932/…
  • 我的 python 代码有效。但我想这不是最佳做法。
  • 不使用枚举而只制作字典会不会有问题。例如,您必须传递 maxPlayers 字符串 'SOLDIER'。我对您的代码知之甚少,不知道这是否容易调整,但大多数人不在 python 中使用枚举。
  • 我不太关心容易与否。我只是想了解在 python 中这样做的最佳实践。

标签: java python enums


【解决方案1】:

让我们记住 Java 中的 enums 到底是什么——static final 类的实例。它们实际上只是命名常量。

通常,与 Java 相比,python 更喜欢更宽松(或者,如果您更喜欢,更灵活)的编码风格。部分原因是没有常数之类的东西,部分原因是相信您的代码的用户不会做疯狂的事情。在这种情况下,您可以通过执行以下操作获得与您的 java 代码类似的效果:

class Role(object):
    class RoleType(object):
        def __init__(self, maxPlayers):
            self.maxPlayers = maxPlayers

    SOLDIER = RoleType(4)
    DEMOMAN = RoleType(2)
    SCOUT = RoleType(4)
    MEDIC = RoleType(2)

然后你可以这样访问它们

s = Role.SOLDIER
print s.maxPlayers  # Prints 4

这个没有做的是阻止你的图书馆的用户创建新的角色。不过,这样做有点尴尬,这应该是在向用户暗示“他们做错了”。

newRole = Role.RoleType(22)  # as an example

如果你走这条路,你或多或少必须忍受它。但是,如果您喜欢使用约定,这通常不会成为问题。他们总是可以访问您定义的值。

【讨论】:

    【解决方案2】:

    如果您正在寻找最佳实践,通常您只需制作一本字典。

    klass = {'SCOUT':4,
             'SOLDIER':4,
             'DEMOMAN':2,
             'MEDIC':2,}
    
    print klass['MEDIC']
    2
    

    如果你希望这是一个类方法,你可以说:

    class Klass:
        def maxPlayers(self, klass):
            return {'SCOUT':4,
                    'SOLDIER':4,
                    'DEMOMAN':2,
                    'MEDIC':2,}[klass]
    

    你会这样使用它:

    print Klass().maxPlayers('MEDIC')
    2
    

    【讨论】:

    • 我喜欢这个答案。但它仍然让我做类似Klass().maxPlayers('MEDIC') 的事情,我认为这不是一个好习惯。因为我必须写'MEDIC'
    • 你反对吗?你想让它做什么?
    • 我认为这里的问题在于,这使得maxPlayers 确实是MEDIC 的事实上的属性变得不太清楚,这是 OP 想要考虑的方式。
    【解决方案3】:

    使用AutoEnum recipe,您的代码可能如下所示:

    class Role(AutoEnum):
    
        SCOUT = 4
        SOLDIER = 4
        DEMOMAN = 2
        MEDIC = 2
    
        def __init__(self, max_players):
            self.max_players = max_players
    

    现在您可以享受新的 Python 枚举 (backported if you don't have 3.4) 带来的好处:

    --> Role.SCOUT
    <Role.SCOUT: 3>
    --> Role.SCOUT.max_players
    4
    

    【讨论】:

      猜你喜欢
      • 2021-04-04
      • 2020-09-27
      • 2020-06-20
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 2011-08-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多