0

I am trying to generate a pseudo random number every time I create a new object object from a specific Class.

import random
class Test (object):
    def __init__ (self,value=random.randint(0,10)):
        self.value=value

this works fine when instantiating the first object from the class, for example

test1=Test()

will give a random integer to the attribute. So the attribute, test1.value will indeed be assigned a random number.

however, any additional objects created from the class will not generate a new random number, but instead, keep the value of the first. So all my additional objects from the class, have the same identical integer value for their .value attribute as the first object. I would have expected the part of the code that generates the random number to run again each time a new object is created.

Feel I'm missing something obvious

petezurich
  • 9,280
  • 9
  • 43
  • 57
Ian Laird
  • 17
  • 5

3 Answers3

2

This is a less obvious version of the "mutable default argument" problem. You need to think like a compiler in this case. The method header signature is evaluated when first encountered:

def __init__ (self,value=random.randint(0,10)):

In defining the method, Python evaluates the signature: randint is called only this one time, yielding a single "random" number that will be used for all default initializations.

To get the functionality you expect, make a default you can interpret as "argument not provided", such as:

def __init__ (self,value=None):
    if value is None:
        value = random.randint(0,10):
Prune
  • 76,765
  • 14
  • 60
  • 81
  • 1
    IMO this isn't a "a less obvious version" of the other problem, it's a different problem with the same root cause. – martineau Jan 17 '20 at 17:44
  • 2
    I agree at my level of programming (and yours, as well). I'm allowing for OP seeing this as separate or barely related. – Prune Jan 17 '20 at 17:45
1

random.randint(0,10) is evaluated immediately and so every class uses the same default argument.

import random
class Test (object):
    def __init__ (self):
        self.value=random.randint(0,10)

If you want to be able to pass a value to override the random value:

import random
class Test (object):
    def __init__ (self, value=None):
        if value is not None:
            self.value = value
        else:
            self.value = random.randint(0,10)
chepner
  • 497,756
  • 71
  • 530
  • 681
clubby789
  • 2,543
  • 4
  • 16
  • 32
1

Try the code below, Read this for more info on this

import random
class Test (object):
    def __init__ (self, value=None):
        if value is None:
            value = random.randint(0,10)
        self.value=value
Shibiraj
  • 769
  • 4
  • 9