3

In the python library pytides, I came across a strange method to initialize a class (the Tide class and its initialization ). I reproduced below a simplified version of the code :

import numpy as np

class Foo(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y

class Foobar(object):
    dtype = np.dtype([('fooObj', object),
                      ('A', float),
                      ('B', float)])

    def __init__(self,model):
        '''model: an ndarray of type Foobar.dtype '''
        self.model = model


# initialize a Foobar object
myFoos = [Foo(4,3),Foo(4,9),Foo(0,2)]
A = [2,3,4]
B = [8,9,0]
model = np.zeros(len(myFoos), dtype = Foobar.dtype)
model['fooObj'] = myFoos     #what is that?!?
model['A'] = A
model['B'] = B
myFoobar = Foobar(model=model)

As I understand, the dtype variable in Foobar is a global variable, but I don't understand what's the point to have it. Is it just here to provide a convenient way to initialize Foobar? Moreover the Foobar class needs an array of Foobar.dtype at construction, is not a sort of cyclic call (which should crash)?

1
  • 4
    The dtype variable in Foobar is not a global variable, it's a class attribute, which is shared by all instances of the Foobar class. Commented Jan 13, 2017 at 8:09

2 Answers 2

1

Foobar.dtype is a class attribute.

That is a variable which is attached to the definition of the class not a single instance of the class. If you're familiar with other popular object-oriented languages, this concept is very similar to a static variables in Java and C#.

Python docs which explains in more detail https://docs.python.org/3/tutorial/classes.html#class-objects


Considering class Foobar in the example you've provided:

Foobar is a class

myFoobar is an instance of Foobar

let's pretend that there's another instance too: yourFoobar

then myFoobar and yourFoobar (and any other instances) may need to be able to have access to some data (in this case a definition of a numpy datatype) which is the same for all instances of Foobar. Thus there's an argument that it should be associated to the class rather than each individual instance. (However there are also arguments that class attributes / static variables do more harm than good: Why are static variables considered evil?)

i.e. avoiding a way of writing it where you allocate each instance of Foobar its own instance of the same numpy dtype definition, such as...

class Foobar(object):
    def __init__(self,model):
        '''model: an ndarray of type self.dtype '''
        self.model = model
        self.dtype = np.dtype([('fooObj', object),
                      ('A', float),
                      ('B', float)])
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @Richard. I think I was confused by the name of the variable (dtype). The Python doc make it clearer.
1

There isn't much that is strange about this initialization, dtype holds the types Foobar requires for the numpy array it receives durings its initialization (model). It's a class attribute, not a global one, so it is shared by all instances of the Foobar class.

The way model is initialized might seem odd, but it is just initializing model based on the name that specifies the field, this might be best demonstrated by printing out model in between the steps:

model['fooObj'] = myFoos
print(model)
array([(<__main__.Foo object at 0x7f125ed93828>, 0.0, 0.0),
       (<__main__.Foo object at 0x7f125ed93940>, 0.0, 0.0),
       (<__main__.Foo object at 0x7f125ed93240>, 0.0, 0.0)], 
      dtype=[('fooObj', 'O'), ('A', '<f8'), ('B', '<f8')])

adds the values for the 'fooObj' object type. While:

model['A'] = A
model['B'] = B

adds the values for the float types 'A' and 'B' respectively.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.