如何在每次迭代中获得Enum属性的随机值?

Lo *_*o L 18 python random lambda enums

我创建了这样的Enum对象:

class Gender(Enum):
    FEMALE = 'female'
    MALE = 'male'
    RANDOM = random.choice([FEMALE, MALE])
Run Code Online (Sandbox Code Playgroud)

我想每次都获得真正的随机值,但它不起作用:

>>> 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'>
Run Code Online (Sandbox Code Playgroud)

我也试过使用lambda,但看起来不太好,虽然它有效:

Gender.RANDOM()
Run Code Online (Sandbox Code Playgroud)

是否有其他方法可以每次获取随机值,而不使用lambda表达式?

我们使用这个枚举对象作为某个方法的参数的默认值,这就是为什么它应该是属性而不是函数,因为当我们使用Gender.FEMALE它时它不是一个函数,它是一个属性,也Gender.RANDOM应该是一个属性:

def full_name(gender=Gender.FEMALE):
    ...


def full_name(gender=Gender.RANDOM):
    ...
Run Code Online (Sandbox Code Playgroud)

Eth*_*man 13

正如其他人所说的那样,最好的方法就是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()))
Run Code Online (Sandbox Code Playgroud)

将此作为函数定义中的默认值将无法满足您的需求.这种方法的标准方法是:

def full_name(gender=None):
    if gender is None:
        gender = Gender.RANDOM   # we get `MALE` or `FEMALE`, not `RANDOM`
Run Code Online (Sandbox Code Playgroud)

这对读者来说会让人感到困惑.使用常规方法会更好:

def full_name(gender=None):
    if gender is None:
        gender = Gender.random()
Run Code Online (Sandbox Code Playgroud)


Abh*_*kan 6

我尝试了一种使用元类的方法.它的工作原理!

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
Run Code Online (Sandbox Code Playgroud)

这里通过使RANDOM_ATTR元类Gender,Gender就像是类的一个对象RANDOM_ATTR,所以Gender属性 RANDOM.

但是,您在问题中描述的以下代码并不像您期望的那样工作.

def full_name(gender=Gender.RANDOM):
    ...
Run Code Online (Sandbox Code Playgroud)

RANDOM物业只会被召唤一次.要知道原因,请阅读此答案.默认参数类似于函数的属性,它只会被初始化一次.

为此,我建议你做这样的事情:

def full_name(gender=None):
    gender = gender or Gender.RANDOM
    ...
Run Code Online (Sandbox Code Playgroud)


Reb*_*que 5

您可能应该在您的中创建一个方法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()
Run Code Online (Sandbox Code Playgroud)