__init__ with multiple list values

Jean-Michel Pichavant jeanmichel at sequans.com
Wed Nov 2 07:04:35 EDT 2011


Gnarlodious wrote:
> Initializing a list of objects with one value:
>
> class Order:
>  def __init__(self, ratio):
>   self.ratio=ratio
>  def __call__(self):
>   return self.ratio
>
> ratio=[1, 2, 3, 4, 5]
> Orders=[Order(x) for x in ratio]
>
>
> But now I want to __init__ with 3 values:
>
> class Order:
>  def __init__(self, ratio, bias, locus):
>   self.ratio=ratio
>   self.bias=bias
>   self.locus=locus
>  def __call__(self):
>   return self.ratio, self.bias, self.locus
>
> ratio=[1, 2, 3, 4, 5]
> bias=[True, False, True, False, True]
> locus=['A', 'B', 'C', 'D', 'E']
> Orders=[Order(x,y,z) for x,y,z in [ratio, bias, locus]]
>
>   
>>>> ValueError: too many values to unpack (expected 3)
>>>>         
>
> How to do it?
>
> -- Gnarlie
>   
I'm a little off topic but you may want to avoid having inconsistent 
interfaces for your class methods, especially when it comes to special 
methods like __init__ and __call__.

Having __call__ return a tuple with different length depending on the 
initialization of the object is a bad idea. You will surely end up in 
unpacking error in the future.

Same things for your attributes, the presence of bias is conditioned by 
the object creation... Very bad idea :o)

o1 = Order([1,2,3])
o2 = Order([1,2,3], [4, 5, 6, [7, 8, 9])

print o1.bias
 > Unknown attribute

ratio, bias, locus = o2.call()

ratio, bias, locus = o1.call()
 > Unpacking error


You could do the following :

class Order:
 def __init__(self, ratio, bias=None, locus=None):
  self.ratio=ratio
  self.bias=bias
  self.locus=locus
 def __call__(self):
  return self.ratio, self.bias, self.locus


It would allow you to create your object with just the ratio and keep a 
consistent interface. Unpacking the __call__ return will never fail, and 
if you're interested in keeping only ratios, then you can write

ratio, _, _ = o1.call()

JM

PS : accessing attributes using the __call__ method sounds like a little 
bit of magic for the lazy guy :o) People expect something to be executed 
when calling an object, not getting its attributes. It would be better 
to stick with the classic way : o1.ratio



More information about the Python-list mailing list