Re: Multiple constructors

2005-02-07 Thread Nick Coghlan
Caleb Hattingh wrote:
Though Alex indicated differently earlier, I intend to always use an 
if  statment inside one constructor to initialise any class in the 
situation  where the arguments may be different in number and type.  I 
don't have the  years of experience that Alex has, however, so I may end 
up regretting it  but right now, it seems to me to be the clearest 
approach in this  situation.
It varies, and often depends on the *promises* a class can make regarding a set 
of inputs. If you can get a similar effect from a bunch of different types of 
inputs, then putting the functionality all in one method is reasonable.

On the other hand, if there is a significant semantic difference associated with 
certain inputs, but you *can* do something useful with them, then a separate 
method may be called for.

The above applies to both ordinary methods and constructors. The builtins and 
the standard library offer many examples of both situations.

Cheers,
Nick.
--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
--
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple constructors

2005-02-06 Thread Leif K-Brooks
Philip Smith wrote:
I don't seem to be able to define multiple versions of __init__ in my matrix 
class (ie to initialise either from a list of values or from 2 dimensions 
(rows/columns)).
You could either use an if statement with *args:
class Matrix(object):
def __init__(self, *args):
if len(args) == 1:
# Initialize from list of values
elif len(args) == 2:
# Initialize from rows/columns
else:
raise TypeError(Constructor accepts 1 or 2 arguments.)
Or with two different functions:
class Matrix(object):
def __init__(self, values):
# Initialize from a list of values
@classmethod
def from_pair(self, rows, columns):
return Matrix([rows, columns]) # Or with the right argument
--
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple constructors

2005-02-06 Thread vincent wehren
Philip Smith wrote:
Call this a C++ programmers hang-up if you like.
I don't seem to be able to define multiple versions of __init__ in my matrix 
class (ie to initialise either from a list of values or from 2 dimensions 
(rows/columns)).

Even if Python couldn't resolve the __init__ to use on the basis of argument 
types surely it could do so on the basis of argument numbers???

At any rate - any suggestions how I code this
Checking the number of arguments ain't all that hard:
class Klass:
   def __init__(*args):
   self.args = args
   if len(self.args) == 1:
   # etc.
This feels rather unpythonic, though. Maybe you could use factory 
functions, forgetting about  __init__ all together (2.2 or higher):

class Klass(object):
def fromList(seq):
result = Klass()
# populate attributes here
# and return the requested object
return result
fromList = staticmethod(fromList)
def fromDimensions(cols, rows):
result = Klass()
# populate attributes here
# and return the requested object
return result
   fromDimensions = staticmethod(fromDimensions)
   #more methods  here
k = Klass.fromList(seq)
etc..
Regards
--
Vincent Wehren



Thanks
Phil 


--
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple constructors

2005-02-06 Thread Leif K-Brooks
Leif K-Brooks wrote:
@classmethod
def from_pair(self, rows, columns):
return Matrix([rows, columns]) # Or with the right argument
Er... I'm not sure why I named that argument self, it should be cls 
if you don't want to  confuse anyone reading your code.
--
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple constructors

2005-02-06 Thread Terry Reedy

Philip Smith [EMAIL PROTECTED] wrote in message 
news:[EMAIL PROTECTED]
 Call this a C++ programmers hang-up if you like.

 I don't seem to be able to define multiple versions of __init__ in my 
 matrix

Correct.

 class (ie to initialise either from a list of values or from 2 dimensions 
 (rows/columns)).

 Even if Python couldn't resolve the __init__ to use on the basis of 
 argument types surely it could do so on the basis of argument numbers???

Variable parameter counts are handled either with default values or the 
*restlist and **keydict mechanisms.

Keep in mind that the compiler cannot, in general, know, at compile time, 
what function object will be bound to a name at run time.  And that you can 
have only bind a name to one object.

 At any rate - any suggestions how I code this

The usual way is to write your own dispatch code to either execute the 
appropriate code block or call the appropriate function.

Or you could write a function of functions that returns a function that 
dispatches to one of the functions according to its arg count.  Something 
like (untested, all exceptions passed through):

def arg_count_dispatcher_maker(*funcs):
def arg_count_dispatcher(*args):
return funcs[len(args)](*args)
return arg_count_dispatcher

which you use like this:
__init__ = arg_count_dispatcher_maker(func0, func1, func2)

Terry J. Reedy 



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple constructors

2005-02-06 Thread Alex Martelli
Philip Smith [EMAIL PROTECTED] wrote:

 Call this a C++ programmers hang-up if you like.
 
 I don't seem to be able to define multiple versions of __init__ in my matrix

Indeed, you can never define ``multiple versions'' of the same name in
the same scope: one scope + one name - one object.

That's what a name (in a given scope, which I won't keep repeating)
MEANS -- in Python as well as in common sense.

 class (ie to initialise either from a list of values or from 2 dimensions
 (rows/columns)).
 
 Even if Python couldn't resolve the __init__ to use on the basis of argument
 types surely it could do so on the basis of argument numbers???

It could, if it didn't think a name is a name is a name.  By sticking to
resolution JUST BY NAME, instead of by name plus who knows what else,
however, Python gains a lot of conceptual simplicity without any loss of
functionality.  Therefore, it's a great design choice.


 At any rate - any suggestions how I code this

My preferred suggestion is to accept that one name === one object: you
want two different objects (constructors), give them two different
names.  One, if you wish, can be __init__ -- the other could be a
staticmethod or even better a classmethod.  Or, have two named methods.

class Matrix(object):
def __init__(self, values):
 init self from values 
@classmethod
def withDimensions(cls, x, y):
return cls([0.0]*x for i in xrange(y))
@classmethod
def fromValues(cls, values):
return cls(values)

Now, Matrix.withDimensions(3, 4) and Matrix.fromValues([[1,2],[3,4]])
are both available and maximally clear, and the latter you can also call
as Matrix([[1,2],[3,4]]) if you wish.  The advantage of using
classmethod is that if you later go and subclass

class SpecialMatrix(Matrix):
   ...

you can call the classmethods on this subclass and get an instance of
the subclass, which can sometimes be handy -- better than using
staticmethods (or factory functions ``outside the class'') and
``hardwiring'' what class they instantiate.


I don't particularly like the concept of a function or method which does
drastically different things -- I'd rather see one function have ONE
function (taking the second repetition as meaning ``role'', ``task'').
This goes for __init__, too.  Still, if you're keen on the idea, you can
of course have your __init__ take optional arguments, check their
presence and/or type, and whatever other devilry; I just think it's not
a very good design, but it does end up with just the same effect as C++
overloaded constructors, which you seem to like.  If you want to do this
all the time, you could even build appropriate infrastructure for this
task -- a little custom descriptor and metaclass, and/or decorators.
Such infrastructure building is in fact fun and instructive -- as long
as you don't fall into the trap of *using* such complications in
production code, where Python's simplicity rules;-).


Alex
 
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple constructors

2005-02-06 Thread Reinhold Birkenfeld
vincent wehren wrote:
 Philip Smith wrote:
 Call this a C++ programmers hang-up if you like.
 
 I don't seem to be able to define multiple versions of __init__ in my matrix 
 class (ie to initialise either from a list of values or from 2 dimensions 
 (rows/columns)).
 
 Even if Python couldn't resolve the __init__ to use on the basis of argument 
 types surely it could do so on the basis of argument numbers???
 
 At any rate - any suggestions how I code this
 
 Checking the number of arguments ain't all that hard:
 
 class Klass:
 def __init__(*args):
 self.args = args
 if len(self.args) == 1:
 # etc.
 
 This feels rather unpythonic, though. 

And it won't work, as `self' is not defined. ;)

Reinhold
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple constructors

2005-02-06 Thread Philip Smith
Thanks to all of you

Some useful ideas in there, even if some of them stretch my current 
knowledge of the language.

C++ to Python is a steep 'unlearning' curve...

Phil

Philip Smith [EMAIL PROTECTED] wrote in message 
news:[EMAIL PROTECTED]
 Call this a C++ programmers hang-up if you like.

 I don't seem to be able to define multiple versions of __init__ in my 
 matrix class (ie to initialise either from a list of values or from 2 
 dimensions (rows/columns)).

 Even if Python couldn't resolve the __init__ to use on the basis of 
 argument types surely it could do so on the basis of argument numbers???

 At any rate - any suggestions how I code this

 Thanks

 Phil
 


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple constructors

2005-02-06 Thread vincent wehren
Reinhold Birkenfeld wrote:
vincent wehren wrote:
Philip Smith wrote:
Call this a C++ programmers hang-up if you like.
I don't seem to be able to define multiple versions of __init__ in my matrix 
class (ie to initialise either from a list of values or from 2 dimensions 
(rows/columns)).

Even if Python couldn't resolve the __init__ to use on the basis of argument 
types surely it could do so on the basis of argument numbers???

At any rate - any suggestions how I code this
Checking the number of arguments ain't all that hard:
class Klass:
   def __init__(*args):
   self.args = args
   if len(self.args) == 1:
   # etc.
This feels rather unpythonic, though. 

And it won't work, as `self' is not defined. ;)
You're right of course!
Note to self: Must stop shooting from the hip ;)
--
Vincent


Reinhold
--
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple constructors

2005-02-06 Thread Steven Bethard
Alex Martelli wrote:
If you want to do this
all the time, you could even build appropriate infrastructure for this
task -- a little custom descriptor and metaclass, and/or decorators.
Such infrastructure building is in fact fun and instructive -- as long
as you don't fall into the trap of *using* such complications in
production code, where Python's simplicity rules;-).
+1 QOTW.
I think this is one of the great truths of Python.  Descriptors, 
metaclasses, decorators, etc. are all there to let you do interesting, 
useful things.  But if you're using such constructs for more than a few 
special cases, then you're missing out on a simple solution that Python, 
almost certainly, makes beautiful.

Steve
--
http://mail.python.org/mailman/listinfo/python-list


Re: Multiple constructors

2005-02-06 Thread Caleb Hattingh
Hi Philip
C++ to Python is a steep 'unlearning' curve...
That's worthy of QOTW.  I decided not to reply to this thread earlier, but  
you just convinced me otherwise :)

I work in Delphi a lot, which is in a lot of respects very similar to C.   
I have come to the conclusion that function overloading was introduced to  
allow the same calling syntax and even functionality to be applied to  
different *types*.  This is a consequence of the fact that in Delphi and  
C, for example, typing is static.

In a dynamic language like python, however, overloading isn't necessary.   
Not only can the *type* of a function argument be determined at run-time,  
the *number* of arguments can as well.

Though Alex indicated differently earlier, I intend to always use an if  
statment inside one constructor to initialise any class in the situation  
where the arguments may be different in number and type.  I don't have the  
years of experience that Alex has, however, so I may end up regretting it  
but right now, it seems to me to be the clearest approach in this  
situation.

thx
Caleb
--
http://mail.python.org/mailman/listinfo/python-list