MOON
MOON

Reputation: 2801

How to pass value to class variable in Python?

Consider the class below:

class cell:
    X_size = 10
    Y_size = 10
    world = np.zeros((X_size,Y_size))

I want to change the class above into the code below and be able to pass X_size, Y_size to an instance:

class cell:
    world = np.zeros((X_size,Y_size))#X_size and Y_size must be passed on the run time

I could do:

class cell:
    def __init__(self, X_size,Y_size):
       self.X_size = X_size
       self.Y_size = Y_size
       world = np.zeros((X_size,Y_size))

The problem is that then every instance makes a new world. I want the world to be created once, to be seen by all the instances and then each new instance modify only one of the world's elements which also could be seen by all the other instances. That is why I use the class variable, but then if I use the class variable, it seems I have to determine X_size and Y_size before hand.

Upvotes: 0

Views: 67

Answers (1)

Jack Smith
Jack Smith

Reputation: 336

To pass arguments to class declarations, one must declare either a superclass with __init_subclass__ (see here) or a metaclass.

__init_subclass__ is the most straight forward way to achieve what you are describing:

class BaseCell:
    def __init_subclass__(cls, *, X_size, Y_size):
        cls.world = np.zeros((X_size, Y_size))

This allows you to pass the size arguments to subclasses of BaseCell, like so:

class MyCell(BaseCell, X_size=10, Y_size=10):
    pass

cells = [MyCell(), MyCell()]

assert cells[0].world is cells[1].world
assert len(cells[0].world) == 10
assert len(cells[0].world[0]) == 10

Then all instances of MyCell will share a single world class attribute, with width 10 and height 10.

Note: Depending on the wider context of what you are trying to achieve, it might be that simply passing the world to each instance constructor might be a more suitable approach (see dependency inversion).

Upvotes: 3

Related Questions