When defining a python class, how to set a random

2019-05-11 15:30发布

问题:

Say I have a class called Person, which will have only the person's name and gender.

The gender should be randomly selected from Male and Female. To do that, I import the random.randint() function. The random gender is determined according to the random int.

import random

class Person:
    alias = random.randint(1, 3)
    if alias == 2:
        gender = 'Male'
    else:
        gender = 'Female'

    def __init__(self, name):
        self.name = name

r = Person('rachel')
s = Person('Stanky')
print(r.gender)
print(s.gender)

However, the result I get for different person from this class all have the same gender. My understanding is the randint is fixed once been generated. My question is how to make it different for each class instance.

回答1:

The reason your never getting a different gender is because the gender attribute is a class variable. Once Python creates your class object Person, the value of gender is never computed again. You need to make the gender variable an instance attribute. That means the gender will be computed on a per instance basis, instead of per class definition. eg:

import random

class Person:
  def __init__(self, name):
      self.name = name
      alias= random.randint(1, 3)
      if alias == 2:
          self.gender = 'Male'
      else:
          self.gender = 'Female'

r= Person('rachel')
s= Person('Stanky')

print(r.gender) 
print(s.gender)

Which outputs

Female
Male

On a side note, I think a much better choice for your task would be to use random.choice() to select a random gender from a list of genders(male or female):

from random import choice

class Person:
  genders = ('Male', 'Female', 'Female')
  def __init__(self, name):
      self.name = name
      self.gender = choice(Person.genders)

rachel = Person('Rachel')
stanky = Person('Stanky')

print(rachel.gender) 
print(stanky.gender)

Notice in my example above, Person.genders is a class variable. This is on purpose. Because we only need to create a list of genders once, we can make the list a class level variable.



回答2:

It seems you already guessed the reason correctly why the gender doesn't change. To solve this you could use a property for gender:

import random

class Person(object):
    def __init__(self, name):
        self.name = name

    @property
    def gender(self):
        try:
            # If it has been defined for the instance, simply return the gender
            return self._gender
        except AttributeError:
            # If it's not defined yet, define it, and then return it
            self._gender = random.choice(['male', 'female'])
            return self._gender

r = Person('rachel')
s = Person('Stanky')
print(r.gender)
print(s.gender)


回答3:

You should put random gender generation under __init__, so that it would be randomly generated for each class instance.

import random

class Person:
    def __init__(self, name):
        self.name = name
        alias= random.randint(1, 3)
        if alias == 2:
            self.gender = 'Male'
        else:
            self.gender = 'Female'

r= Person('rachel')
s= Person('Stanky')
print(r.gender)
print(s.gender)

Three times of results:

$ python classRandom.py 
Male
Female
$ python classRandom.py 
Female
Female
$ python classRandom.py 
Female
Male


回答4:

The gender variable is currently a class variable, that's why it stays the same for all the instance created. You will need to change them into a instance's attribute.

Side note: random.randint(1, 3) will either return 1, 2 or 3 not just 1 or 2. It is not the same as indexing, in which the ending is ignored. Right now, there's a higher chance to be a Female since it could be 1 or 3, so random.randint(1,2) makes more sense. I mentioned this just in case it was not done on purpose. You can also use random.choice, which will choose a random selection from a list.

import random

class Person:

    def __init__(self, name):
        self.name = name
        self.gender= random.choice(["Male", "Female"]) # or random.choice(["Male", "Female", "Female"]) if you want a higher chance of being a female

r= Person('rachel')
s= Person('Stanky')
print(r.gender)
print(s.gender)