Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define properties in __init__

I whish to define properties in a class from a member function. Below is some test code showing how I would like this to work. However I don't get the expected behaviour.

class Basket(object):

  def __init__(self):
    # add all the properties
    for p in self.PropNames():
      setattr(self, p, property(lambda : p) )

  def PropNames(self):
    # The names of all the properties
    return ['Apple', 'Pear']

  # normal property
  Air = property(lambda s : "Air")

if __name__ == "__main__":
  b = Basket()
  print b.Air # outputs: "Air"
  print b.Apple # outputs: <property object at 0x...> 
  print b.Pear # outputs: <property object at 0x...> 

How could I get this to work?

like image 292
pkit Avatar asked Sep 21 '09 15:09

pkit


1 Answers

You need to set the properties on the class (ie: self.__class__), not on the object (ie: self). For example:

class Basket(object):

  def __init__(self):
    # add all the properties
    setattr(self.__class__, 'Apple', property(lambda s : 'Apple') )
    setattr(self.__class__, 'Pear', property(lambda s : 'Pear') )

  # normal property
  Air = property(lambda s : "Air")

if __name__ == "__main__":
  b = Basket()
  print b.Air # outputs: "Air"
  print b.Apple # outputs: "Apple"
  print b.Pear # outputs: "Pear"

For what it's worth, your usage of p when creating lamdas in the loop, doesn't give the behavior that you would expect. Since the value of p is changed while going through the loop, the two properties set in the loop both return the same value: the last value of p.

like image 129
Stef Avatar answered Sep 24 '22 14:09

Stef