__init__ style questions

Duncan Booth duncan.booth at invalid.invalid
Mon Oct 2 13:47:19 CEST 2006

"Will McGugan" <will at willmcgugan.com> wrote:

> Duncan Booth wrote:
>> No it isn't Pythonic. Why not just require 3 values and move the
>> responsibility onto the caller to pass them correctly? They can still
>> use an iterator if they want:
>>     Vector3D(a, b, c)
>>     Vector3D(*some_iter)
> I kind of liked the ability to partially use iterators. It would be
> convenient for reading in from a file for example
> f = file( "model.txt" )
> v1 = Vector3D( f )
> v2 = Vector3D( f )
> v3 = Vector3D( f )
> Which you couldnt do with a tuple, because the * syntac would attempt
> to read the entire file (I think).

Yes, it would, although since the implication is that your class expected 
numbers and the file iterator returns strings I'm not sure how much it 
matters: you are still going to have to write more code than in your 
example above. e.g.

   v1 = Vector3D(float(n) for n in itertools.islice(f, 3))

or with my variant:

   v1 = Vector3D(*(float(n) for n in itertools.islice(f, 3)))

I think my main objection to your code was that it introduced too many ways 
for the constructor to do unexpected things silently. e.g. your suggestion 
Vector3D("abc"), or Vector3D((1,2,3,4)) and I don't like errors going 
uncaught. That's why I think it is better to pass in exactly the arguments 
you need and convert them at the point where you can tell what the ambigous 
construction actually meant. I have no objection though to e.g. a class 
factory method which does all of this:

def fromStringSequence(cls, iter):
    return cls(*(float(n) for n in itertools.islice(iter, 3)))

because that still makes you decide at the point of call whether you want:

   v1 = Vector3D(1, 2, 3)

   v1 = Vector3D.fromStringSequence(f)

More information about the Python-list mailing list