473,569 Members | 2,542 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Multiple constructors

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
Jul 18 '05 #1
12 5301
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("Cons tructor 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
Jul 18 '05 #2
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(fr omList)

def fromDimensions( cols, rows):
result = Klass()
# populate attributes here
# and return the requested object
return result

fromDimensions = staticmethod(fr omDimensions)

#more methods here
k = Klass.fromList( seq)
etc..
Regards
--

Vincent Wehren



Thanks

Phil

Jul 18 '05 #3
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.
Jul 18 '05 #4

"Philip Smith" <as********@blu eyonder.co.uk> wrote in message
news:6S******** **********@fe2. news.blueyonder .co.uk...
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_dispa tcher_maker(*fu ncs):
def arg_count_dispa tcher(*args):
return funcs[len(args)](*args)
return arg_count_dispa tcher

which you use like this:
__init__ = arg_count_dispa tcher_maker(fun c0, func1, func2)

Terry J. Reedy

Jul 18 '05 #5
Philip Smith <as********@blu eyonder.co.uk> 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.withDime nsions(3, 4) and Matrix.fromValu es([[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(M atrix):
...

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

Jul 18 '05 #6
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
Jul 18 '05 #7
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" <as********@blu eyonder.co.uk> wrote in message
news:6S******** **********@fe2. news.blueyonder .co.uk...
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

Jul 18 '05 #8
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

Jul 18 '05 #9
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
Jul 18 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
4369
by: Tupolev | last post by:
Hello, can anyone give me a solution for the following problem????????? I have a class Teller with two possible constructors : Teller() and Teller(int base) Then I have a class TellerInc that is based on the class Teller, also with two possible constructors: TellerInc() and TellerInc(int step). Into the main I want to create an object of...
4
5860
by: Jimmy Johns | last post by:
Hi, I have some classes as follows: #include <iostream> using namespace std; class A { public: virtual A* clone() const = 0; };
5
3396
by: Glen Able | last post by:
Any ideas why compilers seem to give warnings about multiple copy constructors e.g. class A { public: A(A& a); A(const A& a); };
2
3091
by: Neil Zanella | last post by:
Hello, AFAIK the only way to initialize a reference variable defined inside a class is to initialize it in an initializer list. However, when there are multiple constructors, this means that the initializer lists have to be cut and pasted from one constructor to another. This does not seem to lend itself particularly well to...
0
298
by: Gonzo | last post by:
I have the following code. When I serialize the DriverCollection I would like to get both the Driver Collection and the DeletedItems collection. I end up with only the Driver collection. I have tried numerous attributes with no success. Any help would be appreciated... using System; using System.IO; using System.Text; using...
2
22328
by: Mark | last post by:
public class myClass { public myClass(string param1) { //HOW DO I CALL myClass() below?? myClass(); // THIS DOES NOT WORK } public myClass() {
7
16538
by: andrewfsears | last post by:
I have a question: I was wondering if it is possible to simulate the multiple constructors, like in Java (yes, I know that the languages are completely different)? Let's say that I have a class called "Point" which would have two values "x" and "y". Now, let's say if it were the Java version, I would want two constructors: one that...
7
3722
by: Adam Nielsen | last post by:
Hi everyone, I'm having some trouble getting the correct chain of constructors to be called when creating an object at the bottom of a hierarchy. Have a look at the code below - the inheritance goes like this: Shape | +-- Ellipse | +-- Circle
3
2542
by: Jess | last post by:
Hello, I've been reading Effective C++ about multiple inheritance, but I still have a few questions. Can someone give me some help please? First, it is said that if virtual inheritance is used, then "the responsibility for initializing a virtual base is borne by the most derived class in the hierarchy". What does it mean? Initializing...
0
7614
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7924
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8125
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
6284
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5513
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5219
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3642
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1221
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
938
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.