1

After reading this answer, I understand that variables outside of __init__ are shared by all instances of the class, and variables inside __init__ are unique for every instance.

I would like to use the variables that are shared by all instances, to randomly give my instance of the class a unique parameter. This is a shorter version of what I've tried;

from random import choice

class Chromosome(object):
    variable1 = [x for x in range(1,51)]
    variable2 = [x for x in range(51,101)]

    def __init__(self):
        self.var1 = choice(variable1)
        self.var2 = choice(variable2)

My problem is that I can't reach the instance variables when initializing a new instance, the error message says name "variable1" is not defined, is there anyway to get around this?

EDIT: The reason I want to create the lists outside of the __init__ is to save memory, if I create 10.000 chromosomes with around 10-15 variables each, then it's better if I just create the lists once, instead of creating them for every chromosome.

EDIT2: If anyone wants to use it, my final solution involved using random.randrange(a,b+1,2). This picks out a random number (only even numbers) in the range [a,b], including the boundaries.

armara
  • 535
  • 3
  • 17
  • You got an answer to your question, but I should say that your code is terrible. `[x for x in range(1,51)]` can be written simply as `range(1, 51)`. Also, if you just need a random value from a range, no need to create a complete array in memory. `choice(xrange(1, 51))` will do the same, but with no memory waste. – Dmytro Prylipko Jan 19 '19 at 16:17
  • @DmytroPrylipko: In Python 3 `[x for x in range(1,51)]` is not the same as `range(1, 51)`. It's the same as `list(range(1, 51))`. And your suggestion `choice(xrange(1, 51))` could be replaced by `random.randint(1, 50)`. – Matthias Jan 19 '19 at 16:49

3 Answers3

4

You just need to use the class name when referencing it. saying variable1 to Python will make it find a variable from the scope. However, your variable is an attribute of a class.

from random import choice

class Chromosome(object):
    variable1 = [x for x in range(1,51)]
    variable2 = [x for x in range(51,101)]

    def __init__(self):
        self.var1 = choice(Chromosome.variable1)
        self.var2 = choice(Chromosome.variable2)

Equally, you could use self.variable1 since it is just an instance of the class and will have access to the class attributes too.

The main idea here is that when you access any attributes or methods of a class, you must provide an object which has access to these methods, be it the class, a subclass or an instance of either. You wouldn’t call dict.from_keys() as from_keys(), would you?

N Chauhan
  • 3,407
  • 2
  • 7
  • 21
  • this was exactly what I was looking for, big thanks! I can't press the green button yet it's too early, i'll do it when possible – armara Jan 19 '19 at 16:10
3

You could also just use self instead of Chromosome. Also object is not necessary I guess.

from random import choice

class Chromosome():
    variable1 = [x for x in range(1,51)]
    variable2 = [x for x in range(51,101)]

    def __init__(self):
        self.var1 = choice(self.variable1)
        self.var2 = choice(self.variable2)
Venkatachalam
  • 16,288
  • 9
  • 49
  • 77
0

Here's another way: (the above answers are all true)

import random

class Chromosome(object):
    def __init__(self):
        self.var1 = random.choice([x for x in range(1, 51)])
        self.var2 = random.choice([x for x in range(51, 101)])
shahriar
  • 362
  • 4
  • 17