Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在每次迭代中获得枚举属性的随机值?_Python_Random_Lambda_Enums - Fatal编程技术网

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