How to get random value of attribute of Enum on each iteration?
我创建了这样的
1 2 3 4 | class Gender(Enum): FEMALE = 'female' MALE = 'male' RANDOM = random.choice([FEMALE, MALE]) |
我想每次都得到真正的随机值,但它不起作用:
1 2 3 4 5 6 7 8 9 10 11 12 13 | >>> class Gender(Enum): ... MALE = 'male' ... FEMALE = 'female' ... RANDOM = choice([MALE, FEMALE]) ... >>> Gender.RANDOM <Gender.MALE: 'male'> >>> Gender.RANDOM <Gender.MALE: 'male'> >>> Gender.RANDOM <Gender.MALE: 'male'> >>> Gender.RANDOM <Gender.MALE: 'male'> |
我也尝试过使用lambda,但是它看起来不太好,尽管它可以工作:
1 | Gender.RANDOM() |
是否有其他方法可以在不使用lambda表达式的情况下每次获取随机值?
我们使用这个枚举对象作为某个方法的参数的默认值,这就是为什么它应该是一个属性而不是一个函数,因为当我们使用
1 2 3 4 5 6 | def full_name(gender=Gender.FEMALE): ... def full_name(gender=Gender.RANDOM): ... |
正如其他人所说,最好的方法就是让
但是,因为我喜欢拼图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | from enum import Enum import random class enumproperty(object): "like property, but on an enum class" def __init__(self, fget): self.fget = fget def __get__(self, instance, ownerclass=None): if ownerclass is None: ownerclass = instance.__class__ return self.fget(ownerclass) def __set__(self, instance, value): raise AttributeError("can't set pseudo-member %r" % self.name) def __delete__(self, instance): raise AttributeError("can't delete pseudo-member %r" % self.name) class Gender(Enum): FEMALE = 'female' MALE = 'male' @enumproperty def RANDOM(cls): return random.choice(list(cls.__members__.values())) |
在函数定义中将此值用作默认值不会得到您想要的结果。标准方法是:
1 2 3 | def full_name(gender=None): if gender is None: gender = Gender.RANDOM |
这会让读者感到困惑。使用普通方法更好:
1 2 3 | def full_name(gender=None): if gender is None: gender = Gender.random() |
我尝试了一种使用元类的方法。它工作!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import random import enum class RANDOM_ATTR(enum.EnumMeta): @property def RANDOM(self): return random.choice([Gender.MALE, Gender.FEMALE]) class Gender(enum.Enum,metaclass=RANDOM_ATTR): #this syntax works for python3 only FEMALE = 'female' MALE = 'male' print(Gender.RANDOM) #prints male or female randomly |
在这里,通过使
但是,您在问题中描述的下面的代码并不像您期望的那样工作。
1 2 | def full_name(gender=Gender.RANDOM): ... |
为此,我建议你做如下的事情:
1 2 3 | def full_name(gender=None): gender = gender or Gender.RANDOM ... |
你可能应该在你的
1 2 3 4 5 6 7 8 9 10 11 12 | import random import enum class Gender(enum.Enum): FEMALE = 'female' MALE = 'male' @classmethod def get_gender(cls): return random.choice([Gender.FEMALE, Gender.MALE]) Gender.get_gender() |
由于
1 2 3 4 5 6 7 8 9 10 11 | import random import enum class Gender(enum.Enum): MALE = 'male' FEMALE = 'female' @staticmethod def random(): return random.choice(list(Gender)) |
然后,你可以把"我没有选择"的行为转移到函数中,它实际上更合理。
1 2 3 4 | def full_name(gender=None): if gender is None: gender = Gender.random() # ... |
我认为您需要一个随机方法,而不是直接将值保存在变量中,因为如果这样做,值将永远不会改变:
如果你不想要一个函数
随机进口导入枚举
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Gender(enum.Enum): MALE = 'male' FEMALE = 'female' RANDOM = random.choice([MALE, FEMALE]) def __getattribute__(self,item): if item =="RANDOM": Gender.RANDOM = random.choice([self.MALE, self.FEMALE]) return Gender.RANDOM else: return object.__getattribute__(self, item) gender = Gender() |
看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | gender.RANDOM => 'female' gender.RANDOM => 'male' gender.RANDOM => 'male' gender.RANDOM => 'male' gender.RANDOM => 'female' gender.RANDOM => 'male' gender.RANDOM => 'male' gender.RANDOM => 'female' |
尽管在许多情况下修改类可能更清晰、更干燥,但如果您只进行一次修改或不想修改枚举,则可以执行以下操作:
来自文档:"枚举是一组符号名(成员),绑定到唯一的常量值。"您需要像类一样切换到另一个表示。