Python 如何在每次迭代中获得枚举属性的随机值?
我创建了这样的Python 如何在每次迭代中获得枚举属性的随机值?,python,random,lambda,enums,Python,Random,Lambda,Enums,我创建了这样的Enum对象: class Gender(Enum): FEMALE = 'female' MALE = 'male' RANDOM = random.choice([FEMALE, MALE]) 我希望每次都能得到真正的随机值,但它不起作用: >>> class Gender(Enum): ... MALE = 'male' ... FEMALE = 'female' ... RANDOM = choice([MALE
Enum
对象:
class Gender(Enum):
FEMALE = 'female'
MALE = 'male'
RANDOM = random.choice([FEMALE, MALE])
我希望每次都能得到真正的随机值,但它不起作用:
>>> 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表达式
我们使用这个枚举对象作为某个方法的参数的默认值,这就是为什么它应该是一个属性,而不是一个函数,因为当我们使用
Gender.FEMALE
它不是一个函数,它是一个属性和Gender.RANDOM
也应该是一个属性:
def full_name(gender=Gender.FEMALE):
...
def full_name(gender=Gender.RANDOM):
...
我认为您需要一个随机方法,而不是将值直接保存在变量中,因为如果这样做,值将永远不会更改: 如果您不想要函数 随机输入 导入枚举
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()
看:
您可能应该在
Enum
中创建一个方法以获得随机性别:
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()
从文档中可以看出:“枚举是一组绑定到唯一、常量值的符号名(成员)。”
您需要切换到另一种表示形式,如类。我尝试了一种方法。而且它有效
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
这里通过使RANDOM\u ATTR
成为Gender
的元类,Gender
就像类RANDOM\u ATTR
的对象,因此Gender
具有RANDOM
但是,您在问题中描述的以下代码并没有按照您预期的方式工作
def full_name(gender=Gender.RANDOM):
...
RANDOM
属性将只调用一次。要知道原因,请阅读此文。默认参数类似于函数的属性,只能初始化一次
为此,我建议您采取以下措施:
def full_name(gender=None):
gender = gender or Gender.RANDOM
...
尽管在许多情况下修改类可能更清晰、更枯燥,但如果只执行一次或不想修改枚举,可以执行以下操作:
random.choice([enm.value for enm in Gender])
因为random
实际上不是枚举中的一个项目,我认为更连贯的方法是将它精确地作为一个方法而不是一个属性(它毕竟不是!)
然后,您可以将“我没有选择”行为转移到函数中,使其实际上更有意义
def full_name(gender=None):
if gender is None:
gender = Gender.random()
# ...
正如其他人所说,最好的方法是将
random()
作为枚举类上的一个方法,以明确random
不是成员
但是,因为我喜欢拼图:
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()))
在您的
full\u name
定义中,使用Gender.RANDOM
作为默认值不会得到您想要的。这方面的标准是:
def full_name(gender=None):
if gender is None:
gender = Gender.RANDOM # we get `MALE` or `FEMALE`, not `RANDOM`
这会让读者感到困惑。使用常规方法会更好:
def full_name(gender=None):
if gender is None:
gender = Gender.random()
另一个对您的目标有效的选项是:
from enum import Enum
import random
class Gender(Enum):
MALE = object()
FEMALE = object()
@classmethod
def get_random_gender(cls):
gender = random.choice(cls._member_names_)
return gender.lower()
print(Gender.get_random_gender())
>> female
我试过这个,效果不错,但大写的方法看起来很难看。@LkRi我知道它看起来很难看。。我只是以你为例,显然你可以把你的名字want@LkRi现在,看,我改变了它,即使每次调用random方法,你都使用
classmethod
将它存储在random variable中,你的random
签名应该是def random(cls):你的行可以告诉我random=random.choice(list(cls))`@现在我明白你的问题了为什么?保持Enum
有它的优点,特别是对Gender
使用类型。我认为,pythonic的方法就是创建一个函数,在Enum之外返回一个随机的Gender…使用Enum
就可以了。使用RANDOM
作为非常量不是。我们使用此枚举对象作为某些方法的默认值,它应该是Gender.RANDOM
,而不是Gender.get_RANDOM()
或Gender.RANDOM()
。是的,classmethod是我想要的,谢谢你指出默认属性只计算一次(当你定义函数时),所以随机值只随机一次,每次调用该函数时,都会得到相同的初始值。这是我想要更改的常见行为。这是Python的基本行为,您无法更改。我指的是解决方法。当然,我不能改变Python,我也不想这样做。你是对的。它比使用Gender.RANDOM作为默认值更清晰。谢谢虽然它确实有效,但我反对投票,因为EnumMeta
只应在必要时进行子类化,而且还有其他方法可以解决这个问题。有关EnumMeta
子类化的详细信息,请参阅。然而,由于这是一个成功的努力,我提供了一个悬赏。
def full_name(gender=None):
if gender is None:
gender = Gender.RANDOM # we get `MALE` or `FEMALE`, not `RANDOM`
def full_name(gender=None):
if gender is None:
gender = Gender.random()
from enum import Enum
import random
class Gender(Enum):
MALE = object()
FEMALE = object()
@classmethod
def get_random_gender(cls):
gender = random.choice(cls._member_names_)
return gender.lower()
print(Gender.get_random_gender())
>> female