在__str__上调用__init__导致aenum.Enum

时间:2018-03-27 16:30:50

标签: python python-3.x enumeration

在尝试使用愚蠢的东西让我的 str 方法在Enum成员上正常工作时,我发现了一些我并不理解的行为。我知道以下实现是错误的,但我不知道它为什么会这样做。

考虑以下课程:

from aenum import Enum, AutoValue
class MyEnum(str, Enum, settings=AutoValue, init="value data1 data2"):
    __str__ = lambda self: self

    def __new__(cls, name, *args, **kwargs):
        member = str.__new__(cls)
        member._value_ = name
        return member

    @staticmethod
    def _generate_next_value_(name, *args, **kwargs):
        return (name,) + args

    member1 = 1, 2
    member2 = 3, 4

在导入时,这可以执行。 MyEnum.member1.data1 == 1MyEnum.member1.data2 == 2。但是,当我调用str(MyEnum.member1)时,会抛出一个异常,说“缺少'data2'的值”。我在这里查看了代码,似乎正在调用MyEnum.member1.__str__().__init__(MyEnum.member1.__str__())。我不是肯定的是通话路径,但那是结果。由于MyEnum.__init__ is Enum.__init__我们正在使用AutoValue,因此 init 方法需要两个参数。它正在尝试设置member1.data1 = member1,而member1.data2没有值。

要明确,我知道正确的解决方案是将__str__方法实现为__str__ = str.__str__。但是,由于isinstance(MyEnum.member1, str) == True str 需要返回一个str ..我不清楚为什么上面的实现会表现如何。

  1. 为什么要调用__init__
  2. 为什么返回self是不够的,因为selfstr
  3. 在某种程度上无关,为什么我不能在没有设置“价值”的情况下实现这一点?如果你带走,从init字符串中取值,删除__new___generate_next_value_方法,在导入TypeError时会抛出str() argument 2 must be str, not int(... / aenum / 初始化的.py:1302)。

2 个答案:

答案 0 :(得分:1)

在对象上调用str的行为类似于调用任何其他类型:它在您的对象上调用str.__new__,然后如果结果是str的实例,则调用{{1}结果。

__init__调用您的str.__new__方法,该方法返回__str__。由于返回值是MyEnum的实例,因此下一步是调用str方法。那是意外的__init__来电的来源。

答案 1 :(得分:1)

@ user2357112拥有它的权利。

详细说明你的观点:

  
      
  1. 为什么返回self是不够的,因为selfstr
  2.   

self不是str,它是MyEnum,它是str子类 - 拥有它自己的__init__子类str 1}},然后被调用。 __init__类没有UserSchema.pre('save', (next) => { console.log('Pre-Save Hash has fired.') let user = this; bcrypt.genSalt(10, (err, salt) => { if (err) console.error(err); bcrypt.hash(user.password, salt, (err, hash) => { user.password = hash; next(); }); }); }); 方法。