Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement property() with dynamic name (in python)

I am programming a simulations for single neurons. Therefore I have to handle a lot of Parameters. Now the Idea is that I have two classes, one for a SingleParameter and a Collection of parameters. I use property() to access the parameter value easy and to make the code more readable. This works perfect for a sinlge parameter but I don't know how to implement it for the collection as I want to name the property in Collection after the SingleParameter. Here an example:

class SingleParameter(object):
  def __init__(self, name, default_value=0, unit='not specified'):
    self.name = name
    self.default_value = default_value
    self.unit = unit
    self.set(default_value)
  def get(self):
    return self._v
  def set(self, value):
    self._v = value
  v = property(fget=get, fset=set, doc='value of parameter')

par1 = SingleParameter(name='par1', default_value=10, unit='mV')
par2 = SingleParameter(name='par2', default_value=20, unit='mA')

# par1 and par2 I can access perfectly via 'p1.v = ...'
# or get its value with 'p1.v'

class Collection(object):
  def __init__(self):
    self.dict = {}
  def __getitem__(self, name):
    return self.dict[name] # get the whole object
    # to get the value instead:
    # return self.dict[name].v
  def add(self, parameter):
    self.dict[parameter.name] = parameter
    # now comes the part that I don't know how to implement with property():
    # It shoule be something like
    # self.__dict__[parameter.name] = property(...) ?

col = Collection()
col.add(par1)
col.add(par2)
col['par1'] # gives the whole object

# Now here is what I would like to get:
# col.par1 -> should result like col['par1'].v
# col.par1 = 5 -> should result like col['par1'].v = 5

Other questions that I put to understand property():

  • Why do managed attributes just work for class attributes and not for instance attributes in python?
  • How can I assign a new class attribute via __dict__ in python?
like image 736
Philipp der Rautenberg Avatar asked Jan 05 '09 12:01

Philipp der Rautenberg


People also ask

How do you create a dynamic object name in Python?

The creation of a dynamic variable name in Python can be achieved with the help of iteration. Along with the for loop, the globals() function will also be used in this method. The globals() method in Python provides the output as a dictionary of the current global symbol table.

What does property () do in Python?

Python's property() is the Pythonic way to avoid formal getter and setter methods in your code. This function allows you to turn class attributes into properties or managed attributes. Since property() is a built-in function, you can use it without importing anything.

How do you dynamically create a class object in Python?

Classes can be dynamically created using the type() function in Python. The type() function is used to return the type of the object. The above syntax returns the type of object.


2 Answers

Look at built-in functions getattr and setattr. You'll probably be a lot happier.

like image 52
S.Lott Avatar answered Oct 20 '22 02:10

S.Lott


Using the same get/set functions for both classes forces you into an ugly hack with the argument list. Very sketchy, this is how I would do it:

In class SingleParameter, define get and set as usual:

def get(self):
  return self._s
def set(self, value):
  self._s = value

In class Collection, you cannot know the information until you create the property, so you define the metaset/metaget function and particularize them only later with a lambda function:

def metaget(self, par):
  return par.s
def metaset(self, value, par):
  par.s = value
def add(self, par):
  self[par.name] = par
  setattr(Collection, par.name,
    property(
      fget=lambda x : Collection.metaget(x, par),
      fset=lambda x, y : Collection.metaset(x,y, par))
like image 37
meteore Avatar answered Oct 20 '22 01:10

meteore