1

I'm still new to python and this is probably going be one of those (stupid) boring questions. However, any help will be much appreciated. I'm programing something that involves many variables and I've decided to use a class to encapsulate all variables (hopefully making it easier to "read" for me as time passes), but it's not working as I thought it will. So, without further ado here is a part of the class that captures the gist.

import numpy as np

class variable:
    def __init__(self, length):
        self.length = length # time length`
    def state_dynamic(self):
        length = self.length
        return np.zeros((2, np.size(length)))
    def state_static(self):
        length = self.length
        return np.zeros((2, np.size(length)))        
    def control_dynamic(self):
        length = self.length
        return np.zeros((2, np.size(length)))        
    def control_static(self):
        length = self.length
        return np.zeros((2, np.size(length)))
    def scheduling(self):
        length = self.length
        return np.zeros(np.size(length))
    def disturbance(self):
        length = self.length
        dummy = np.random.normal(0., 0.1, np.size(length))
        for i in range(20):
            dummy[i+40] = np.random.normal(0., 0.01) + 1.
        dummy[80:100] = 0.
        return dummy

I've also tried this one:

import numpy as np

class variable:
    def __init__(self, type_1, type_2, length):
        self.type_1 = type_1 # belongs to set {state, control, scheduling, disturbance}
        self.type_2 = type_2 # belongs to set {static, dynamic, none}
        self.length = length # time length
    def type_v(self):
        type_1 = self.type_1
        type_2 = self.type_2
        length = self.length
        if type_1 == 'state' and type_2 == 'dynamic':
            return np.zeros((2, np.size(length)))
        elif type_1 == 'state' and type_2 == 'static':
            return np.zeros((2, np.size(length)))
        elif type_1 == 'control' and type_2 == 'dynamic':
            return np.zeros((2, np.size(length)))
        elif type_1 == 'control' and type_2 == 'static':
            return np.zeros((2, np.size(length)))
        elif type_1 == 'scheduling' and type_2 == 'none':
            return np.zeros(np.size(length))        
        elif type_1 == 'disturbance' and type_2 == 'none':
            dummy = np.random.normal(0., 0.1, np.size(length))
            for i in range(20):
            dummy[i+40] = np.random.normal(0., 0.01) + 1.
            dummy[80:100] = 0.
            return dummy

Now, using the first one (the outcome is the same for the second class as well), when I write the following, say:

In [2]: time = np.linspace(0,10,100)

In [5]: v = variable(time)

In [6]: v1 = v.state_dynamic

In [7]: v1.size
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/home/<ipython-input-7-e6a5d17aeb75> in <module>()
----> 1 v1.size

AttributeError: 'function' object has no attribute 'size'

In [8]: v2 = variable(np.size(time)).state_dynamic

In [9]: v2
Out[9]: <bound method variable.state_dynamic of <__main__.variable instance at 0x3ad0a28>>

In [10]: v1[0,0]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/<ipython-input-10-092bc2b9f982> in <module>()
----> 1 v1[0,0]

TypeError: 'instancemethod' object has no attribute '__getitem__'

I was hoping that by writing

variable(length).state_dynamic

I'll access

np.zeros((2, np.size(length)))

Anyway, if I made something utterly stupid please let me know :) and feel free to give any kind of advice. Thank you in advance for your time and kind attention. Best regards.

EDIT #1:

@wheaties:

Thank you for a quick reply and help :)

What I'm currently trying to do is the following. I have to plot several "variables", e.g., state, control, dropouts, scheduling and disturbances. All the variables depend on three parameters, namely, dynamic, static and horizon. Further, state and control are np.zeros((2, np.size(length))), dropouts and scheduling are np.zeros(np.size(length)) and disturbance has specific form (see above). Initially, I declared them in the script and the list is very long and looks ugly. I use these variables to store responses of dynamical systems considered and to plot them. I don't know if this is a good way of doing this and if you have any suggestion please share.

Thanks again for your help.

605na
  • 85
  • 1
  • 5
  • I don't think this `variable` class properly represents the concept of a variable. For one thing, if `v` is a `variable`, then `v.state_dynamic() is not v.state_dynamic()`. Any changes you make to `v.state_dynamic()` will effectively be ignored, because the next time you access `v.state_dynamic()`, you'll get a new array. Why not just use actual variables? – user2357112 supports Monica Jul 17 '13 at 03:28

2 Answers2

5

Do you mean you want named access to a bunch of state information? The ordinary python idiom for class variables would look like this:

class Variable(object):
   def __init__ (self, state_dynamic, state_static, control_static, control_dynamic, scheduling):
      self.state_dynamic = state_dynamic
      self.state_static = state_static
      self.control_static = control_static
      self.control_dynamic = control_dynamic
      self.scheduling = control_dynamic

Which essentially creates a bucket with named fields that hold values you put in via the constructor. You can also create lightweight data classes using the namedtuple factory class, which avoids some of the boilerplate.

The other python idiom that might apply is to use the @property decorator as in @wheaties answer. This basically disguises a function call to make it look like a field. If what you're doing can be reduced to a functional basis this would make sense. This is an example of the idea (not based on your problem set, since I'm not sure I grok what you're doing in detail with all those identical variables) -- in this case I'm making a convenience wrapper for pulling individual flags out that are stored in a python number but really make a bit field:

class Bits(object):
   def __init__(self, integer):
      self.Integer = integer # pretend this is an integer between 0 and 8 representing 4 flags

   @property 
   def locked(self):
      # low bit = locked
      return self.Integer & 1 == 1

   @property
   def available(self):
     return self.Integer & 2 == 2

   @property
   def running_out_of_made_up_names(self):
     return self.Integer & 4 == 4

   @property
   def really_desperate_now(self):
     return self.Integer & 8 == 8

 example = Bits(7)
 print example.locked
 # True
 print example.really_desperate_now
 # False
theodox
  • 11,352
  • 3
  • 20
  • 35
  • Hi and thanks :) I used the second idiom. However, I ended up not trimming the main code much... I think I asked a wrong question... Don't know if comment section is the right place to ask, but, what's a good way to organize a code if many variables of a system considered have to be plotted? Namely, I'm simulating a Networked Control System, and have many variables that I have to plot. Declaring all variables for plotting in main script looks very ugly. I thought that by making a class "variables" I would trim the code and make their names as functions, e.g., variable(state,dynamic,horizon=2). – 605na Jul 18 '13 at 02:52
  • It's ok to refactor the question as a response to feedback - happens all the time. You might want to look at some perennial python questions like http://stackoverflow.com/questions/36932/how-can-i-represent-an-enum-in-python and http://stackoverflow.com/questions/1849311/how-should-i-organize-python-source-code You might also want to see if you can subdivide the problem more finely with a deeper class hierarchy - the amount of duplication in the example suggests that what you have as functions might want to be class instances – theodox Jul 18 '13 at 18:09
  • And -- one good rule of thumb in pythonland: the better the code is, the shorter and more readable it is. If the code seems unwieldy, it's a refactor waiting to happen :) – theodox Jul 18 '13 at 18:12
  • Hi again. Thanks for the tips, I've skimmed through the references you gave and think it will help me a lot, again thanks :) – 605na Jul 18 '13 at 23:23
1

A method in Python is a function. If you want to get a value from a member function you have to end it with (). That said, some refactoring may help eliminate boilerplate and reduce the problem set size in your head. I'd suggest using a @property for some of these things, combined with a slight refactor

class variable:
    def __init__(self, length):
    self.length = length # time length`

@property
def state_dynamic(self):
    return self.np_length    
@property
def state_static(self):
    return self.np_length
@property
def control_dynamic(self):
    return self.np_length
@property
def control_static(self):
    return self.np_length
@property
def scheduling(self):
    return self.np_length
@property
def np_length(self):
    return np.zeros(2, np.size(self.length))

That way you can use those functions as you would a member variable like you tried before:

var = variable(length).state_dynamic

What I can't tell from all this is what the difference is between all these variables? I don't see a single one. Are you assuming that you have to access them in order? If so, that's bad design and a problem. Never make that assumption.

wheaties
  • 34,173
  • 12
  • 82
  • 126