I have created such Enum
object:
class Gender(Enum):
FEMALE = 'female'
MALE = 'male'
RANDOM = random.choice([FEMALE, MALE])
and i want to get really random value each time, but it does not work:
>>> 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'>
I have also tried use lambda, but it's looks not so good, although it works:
Gender.RANDOM()
Are there other way to get random values each time, without using lambda expressions?
We use this enum object as default value of the argument of the some method that's why it should be an attribute, not a function, because when we use Gender.FEMALE
it is not a function, it's an attribute and Gender.RANDOM
should be an attribute too:
def full_name(gender=Gender.FEMALE):
...
def full_name(gender=Gender.RANDOM):
...
Inside randomDirection(), we call the method nextInt() with an integer argument. The nextInt() method returns a random number to access the directions array; therefore, we need to make sure the integer is not out of the bounds of the array by passing a bound argument to nextInt().
Summary. Use enum auto() class to generate unique values for enumeration members.
This method use the java. util. Random to create a random value. This random value then will be used to pick a random value from the enum.
By definition, the enumeration member values are unique. However, you can create different member names with the same values.
As others have said, the best way is to just make random()
be a method on your enum class to make it clear that RANDOM
is not a member.
However, since I like puzzles:
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()))
In your full_name
definition, using Gender.RANDOM
as a default value will not get you what you want. The standard for such is:
def full_name(gender=None):
if gender is None:
gender = Gender.RANDOM # we get `MALE` or `FEMALE`, not `RANDOM`
Which is going to be confusing to the reader. This is much better using a normal method:
def full_name(gender=None):
if gender is None:
gender = Gender.random()
I tried a way with metaclasses. And it works!
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
Here by making RANDOM_ATTR
the metaclass of Gender
, Gender
is like an object of class RANDOM_ATTR
, so Gender
has the property RANDOM
.
However,the below code you described in your question doesn't work the way you expect.
def full_name(gender=Gender.RANDOM):
...
The RANDOM
property will be called only once. To know why, please read this answer. Default arguments are like attributes to function, which will be initialised only once.
For that i would suggest you do something like this:
def full_name(gender=None):
gender = gender or Gender.RANDOM
...
You probably should create a method in your Enum
to obtain a random gender:
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With