Re: More __init__ methods

2008-11-07 Thread Mr . SpOOn
On Fri, Nov 7, 2008 at 7:02 PM, Marc 'BlackJack' Rintsch <[EMAIL PROTECTED]> 
wrote:
>> What if I need the parse method to be called in other parts of the
>> program?
>
> I don't understand!?  Then you call it from those other parts.

Yes, you're right. Don't know why, but I was thinking to use
@classmethod just for the alternative constructors.
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-07 Thread Terry Reedy

Duncan Booth wrote:

Mr.SpOOn <[EMAIL PROTECTED]> wrote:


Now I must pass a and b to the main constructor and calculate them in
the classmethods.

class foo:
def __init__(self, a, b):
 self.a = a
 self.b = b

@classmethod
def from_string(self, ..):
  ...
  ...

What I mean is: I can't use anymore __init__ as the default
constructor, but I always have to specify the way I'm creating my
object. Am I right? I'm asking just to be sure I have understood.


There is a really big advantage to being explicit in this situation: you no 
longer have to make sure that all your constructors use a unique set of 
types. Consider:


class Location(object):
def __init__(self, lat, long): ...

@classmethod
def from_city(name): ...

@classmethod
def from_postcode(name): ...

'from_string' is a bad name here for your factory method: you should try to 
make it clear what sort of string is expected.


One built-in model for .__init__ + .from_data is dict.  __init__ can 
take either one iterable or several keywords.  In either case, it gets a 
set of key:value pairs.  .from_keys take a set of keys and an optional 
value to override None that is matched with all keys.


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


Re: More __init__ methods

2008-11-07 Thread Marc 'BlackJack' Rintsch
On Fri, 07 Nov 2008 17:23:21 +0100, Mr.SpOOn wrote:

> On Fri, Nov 7, 2008 at 4:16 PM, Duncan Booth
> <[EMAIL PROTECTED]> wrote:
>> There is a really big advantage to being explicit in this situation:
>> you no longer have to make sure that all your constructors use a unique
>> set of types. Consider:
>>
>> class Location(object):
>>def __init__(self, lat, long): ...
>>
>>@classmethod
>>def from_city(name): ...
>>
>>@classmethod
>>def from_postcode(name): ...
>>
>> 'from_string' is a bad name here for your factory method: you should
>> try to make it clear what sort of string is expected.
> 
> Yes, that's what I was going to do.
> But, for example, I have a parse method to create such object from a
> string. So I need to call this method to actually create the object. Now
> I must put the code of the parse method into the @classmethod
> constructor.

You can still spread it over other `classmethod()`\s or `staticmethod()`s 
or even plain functions at module level.

> What if I need the parse method to be called in other parts of the
> program?

I don't understand!?  Then you call it from those other parts.

Ciao,
Marc 'BlackJack' Rintsch
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-07 Thread Mr . SpOOn
On Fri, Nov 7, 2008 at 4:16 PM, Duncan Booth
<[EMAIL PROTECTED]> wrote:
> There is a really big advantage to being explicit in this situation: you no
> longer have to make sure that all your constructors use a unique set of
> types. Consider:
>
> class Location(object):
>def __init__(self, lat, long): ...
>
>@classmethod
>def from_city(name): ...
>
>@classmethod
>def from_postcode(name): ...
>
> 'from_string' is a bad name here for your factory method: you should try to
> make it clear what sort of string is expected.

Yes, that's what I was going to do.
But, for example, I have a parse method to create such object from a
string. So I need to call this method to actually create the object.
Now I must put the code of the parse method into the @classmethod
constructor.

What if I need the parse method to be called in other parts of the program?
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-07 Thread Marc 'BlackJack' Rintsch
On Fri, 07 Nov 2008 15:16:29 +, Duncan Booth wrote:

> 'from_string' is a bad name here for your factory method: you should try
> to make it clear what sort of string is expected.

When I use a `from_string()` factory I usually make sure it can parse the 
`str()` form of that type or that there is a `to_string()` as reverse 
operation.

Ciao,
Marc 'BlackJack' Rintsch
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-07 Thread Duncan Booth
Mr.SpOOn <[EMAIL PROTECTED]> wrote:

> Now I must pass a and b to the main constructor and calculate them in
> the classmethods.
> 
> class foo:
> def __init__(self, a, b):
>  self.a = a
>  self.b = b
> 
> @classmethod
> def from_string(self, ..):
>   ...
>   ...
> 
> What I mean is: I can't use anymore __init__ as the default
> constructor, but I always have to specify the way I'm creating my
> object. Am I right? I'm asking just to be sure I have understood.

There is a really big advantage to being explicit in this situation: you no 
longer have to make sure that all your constructors use a unique set of 
types. Consider:

class Location(object):
def __init__(self, lat, long): ...

@classmethod
def from_city(name): ...

@classmethod
def from_postcode(name): ...

'from_string' is a bad name here for your factory method: you should try to 
make it clear what sort of string is expected.

-- 
Duncan Booth http://kupuguy.blogspot.com
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-07 Thread Mr . SpOOn
On Thu, Nov 6, 2008 at 11:00 PM, Ben Finney
<[EMAIL PROTECTED]> wrote:
> Yes, the main reason is that it kills duck typing. The initialiser
> should *use* the parameters passed, and allow exceptions to propagate
> back to the caller if the parameters don't behave as expected.
>
> Another good reason to avoid the above style is that it's far too
> complex. Different behaviours should be in different functions.

Sorry for double posting, but in this way it seems I can't use
instance method inside the classmethod. Probably it is the right
behavior, but if I use this @classmethod style to simplify the
__init__ method, now I should move code from instance method inside
the classmethods.

In this way I'm kinda mixing things. I mean, if to construct an object
I have to use different methods, what can I do? Or am I missing
something, as usual?
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-07 Thread Mr . SpOOn
On Thu, Nov 6, 2008 at 11:00 PM, Ben Finney
<[EMAIL PROTECTED]> wrote:
> Yes, the main reason is that it kills duck typing. The initialiser
> should *use* the parameters passed, and allow exceptions to propagate
> back to the caller if the parameters don't behave as expected.
>
> Another good reason to avoid the above style is that it's far too
> complex. Different behaviours should be in different functions.

Ok, thanks.
Is there a good book or source where I can read about such topics?
Core Python Programming doesn't seem to talk about decorators. Maybe
it's too old?
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-06 Thread Ben Finney
Arnaud Delobelle <[EMAIL PROTECTED]> writes:

> Ben Finney <[EMAIL PROTECTED]> writes:
> [...]
> > All you need to know to understand the above is that it will have
> > essentially the same result as:
> >
> > class A(object):
> > # ...
> >
> > def _from_string(cls, s):
> > # ...
> > return cls(a, b, c)
> > from_string = classmethod(_from_string)
> > del _from_string
> >
> > without the intermediate binding of the ‘_from_string’ name.
> 
> So you mean it is the same as:
> 
> class A(object):
> # ...
> 
> def from_string(cls, s):
> # ...
> from_string = classmethod(from_string)

Sure, but I figured I would make the steps more explicit.

-- 
 \  “Writing a book is like washing an elephant: there no good |
  `\place to begin or end, and it's hard to keep track of what |
_o__)  you've already covered.” —anonymous |
Ben Finney
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-06 Thread Ben Finney
Larry Bates <[EMAIL PROTECTED]> writes:

> Is there some reason not to use something like the following?
> 
> class foo:
> def __init__(self, val):
> self.a = 0
> self.b = 0
> 
> if isinstance(val, basestring):
> #
> # do something to calculate "a and b"
> #
> 
> elif isintance(val, int):
> #
> # do something else to calculate "a and b"
> #
> 
> elif isinstance(val, someinstance)
> #
> # do something else to calculate "a and b"
> #
> 
> else:
> #
> # Don't know what to do with unknown type
> #
> raise ValueError()

Yes, the main reason is that it kills duck typing. The initialiser
should *use* the parameters passed, and allow exceptions to propagate
back to the caller if the parameters don't behave as expected.

Another good reason to avoid the above style is that it's far too
complex. Different behaviours should be in different functions.

-- 
 \  “Friendship is born at that moment when one person says to |
  `\another, ‘What! You too? I thought I was the only one!’” —C.S. |
_o__)Lewis |
Ben Finney
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-06 Thread Ben Finney
Mr.SpOOn <[EMAIL PROTECTED]> writes:

> class foo:
> def __init__(self, a, b):
>  self.a = a
>  self.b = b
> 
> @classmethod
> def from_string(self, ..):
>   ...
>   ...
> 
> What I mean is: I can't use anymore __init__ as the default
> constructor, but I always have to specify the way I'm creating my
> object. Am I right? I'm asking just to be sure I have understood.

Yes, that's what the above design requires. You code ‘foo.__init__’
for the common use case, and create ‘foo.from_bar’ classmethod factory
functions for other cases. The caller then needs to specify which case
is being requested.

-- 
 \ “I was in the first submarine. Instead of a periscope, they had |
  `\   a kaleidoscope. ‘We're surrounded.’” —Steven Wright |
_o__)  |
Ben Finney
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-06 Thread Arnaud Delobelle
Ben Finney <[EMAIL PROTECTED]> writes:
[...]
> All you need to know to understand the above is that it will have
> essentially the same result as:
>
> class A(object):
> # ...
>
> def _from_string(cls, s):
> # ...
> return cls(a, b, c)
> from_string = classmethod(_from_string)
> del _from_string
>
> without the intermediate binding of the ‘_from_string’ name.

So you mean it is the same as:

class A(object):
# ...

def from_string(cls, s):
# ...
from_string = classmethod(from_string)

:)

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


Re: More __init__ methods

2008-11-06 Thread Ben Finney
Mr.SpOOn <[EMAIL PROTECTED]> writes:

> On Thu, Nov 6, 2008 at 4:59 PM, Marc 'BlackJack' Rintsch <[EMAIL PROTECTED]> 
> wrote:
> > class A(object):
> >def __init__(self, a, b, c):
> >self.a = a
> ># ...
> >
> >@classmethod
> >def from_string(cls, s):
> ># ...
> >return cls(a, b, c)
> 
> Thanks.
> I think it's time to study decorators.

Studying decorators is a good idea, but in this instance it's not
necessary. The above is merely using decorator syntax to apply the
‘classmethod’ type to a function.

All you need to know to understand the above is that it will have
essentially the same result as:

class A(object):
# ...

def _from_string(cls, s):
# ...
return cls(a, b, c)
from_string = classmethod(_from_string)
del _from_string

without the intermediate binding of the ‘_from_string’ name.

-- 
 \  “The best way to get information on Usenet is not to ask a |
  `\   question, but to post the wrong information.” —Aahz |
_o__)  |
Ben Finney
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-06 Thread Larry Bates

Mr.SpOOn wrote:

On Thu, Nov 6, 2008 at 7:44 PM, Tim Golden <[EMAIL PROTECTED]> wrote:

While that's no bad thing, you don't really need to do
that simply to understand these examples: they're just
saying "do whatever you need to to make these method
class methods, not instance methods".


Yes.

I think this changes the design of my class.

I mean, till now I had something like:

class foo:
def __init__(self, string=None, integer=None, someinstance=None):
 self.a = 0
 self.b = 0

 if string:
# do something to calculate "a and b"
 elif integer:
# do something else to calculate "a and b"
 ...
 ...

So I used different methods to calculate the same variables.

Now I must pass a and b to the main constructor and calculate them in
the classmethods.

class foo:
def __init__(self, a, b):
 self.a = a
 self.b = b

@classmethod
def from_string(self, ..):
  ...
  ...

What I mean is: I can't use anymore __init__ as the default
constructor, but I always have to specify the way I'm creating my
object. Am I right? I'm asking just to be sure I have understood.


Is there some reason not to use something like the following?

class foo:
def __init__(self, val):
self.a = 0
self.b = 0

if isinstance(val, basestring):
#
# do something to calculate "a and b"
#

elif isintance(val, int):
#
# do something else to calculate "a and b"
#

elif isinstance(val, someinstance)
#
# do something else to calculate "a and b"
#

else:
#
# Don't know what to do with unknown type
#
raise ValueError()



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


Re: More __init__ methods

2008-11-06 Thread Mr . SpOOn
On Thu, Nov 6, 2008 at 7:44 PM, Tim Golden <[EMAIL PROTECTED]> wrote:
> While that's no bad thing, you don't really need to do
> that simply to understand these examples: they're just
> saying "do whatever you need to to make these method
> class methods, not instance methods".

Yes.

I think this changes the design of my class.

I mean, till now I had something like:

class foo:
def __init__(self, string=None, integer=None, someinstance=None):
 self.a = 0
 self.b = 0

 if string:
# do something to calculate "a and b"
 elif integer:
# do something else to calculate "a and b"
 ...
 ...

So I used different methods to calculate the same variables.

Now I must pass a and b to the main constructor and calculate them in
the classmethods.

class foo:
def __init__(self, a, b):
 self.a = a
 self.b = b

@classmethod
def from_string(self, ..):
  ...
  ...

What I mean is: I can't use anymore __init__ as the default
constructor, but I always have to specify the way I'm creating my
object. Am I right? I'm asking just to be sure I have understood.
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-06 Thread Tim Golden

Mr.SpOOn wrote:

On Thu, Nov 6, 2008 at 4:59 PM, Marc 'BlackJack' Rintsch <[EMAIL PROTECTED]> 
wrote:

class A(object):
   def __init__(self, a, b, c):
   self.a = a
   # ...

   @classmethod
   def from_string(cls, s):
   # ...
   return cls(a, b, c)


Thanks.
I think it's time to study decorators.



While that's no bad thing, you don't really need to do
that simply to understand these examples: they're just
saying "do whatever you need to to make these method
class methods, not instance methods".

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


Re: More __init__ methods

2008-11-06 Thread Mr . SpOOn
On Thu, Nov 6, 2008 at 4:59 PM, Marc 'BlackJack' Rintsch <[EMAIL PROTECTED]> 
wrote:
> class A(object):
>def __init__(self, a, b, c):
>self.a = a
># ...
>
>@classmethod
>def from_string(cls, s):
># ...
>return cls(a, b, c)

Thanks.
I think it's time to study decorators.
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-06 Thread Marc 'BlackJack' Rintsch
On Thu, 06 Nov 2008 16:49:08 +0100, Mr.SpOOn wrote:

> I know there can be only one __init__ method (at least, I think).
> 
> Often I need an object to be created in different ways, for example
> passing a string as argument, or an integer, or another object. To
> achieve this I put the default value of the arguments to None and then I
> some if...elif inside the __init__.
> 
> Is this a good practice? It actually works, but sometimes I think that
> in this way the __init__ method can become too complicated, for example
> when an object can be created using more than one argument and in
> different combinations.

I'm usually using `classmethod()`\s as alternative "constructors" then. 
For example:

class A(object):
def __init__(self, a, b, c):
self.a = a
# ...

@classmethod
def from_string(cls, s):
# ...
return cls(a, b, c)

Ciao,
Marc 'BlackJack' Rintsch
--
http://mail.python.org/mailman/listinfo/python-list


Re: More __init__ methods

2008-11-06 Thread Tim Golden

Mr.SpOOn wrote:

Hi,
I know there can be only one __init__ method (at least, I think).

Often I need an object to be created in different ways, for example
passing a string as argument, or an integer, or another object. To
achieve this I put the default value of the arguments to None and then
I some if...elif inside the __init__.

Is this a good practice? It actually works, but sometimes I think that
in this way the __init__ method can become too complicated, for
example when an object can be created using more than one argument and
in different combinations.


My own approach -- and I don't think I'm unique in this -- is
to use class methods called things like "from_string" or "from_date",
possibly with a convenience function which tries to guess from a
passed-in parameter which of them is to be used.

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


More __init__ methods

2008-11-06 Thread Mr . SpOOn
Hi,
I know there can be only one __init__ method (at least, I think).

Often I need an object to be created in different ways, for example
passing a string as argument, or an integer, or another object. To
achieve this I put the default value of the arguments to None and then
I some if...elif inside the __init__.

Is this a good practice? It actually works, but sometimes I think that
in this way the __init__ method can become too complicated, for
example when an object can be created using more than one argument and
in different combinations.

Hope my doubt is clear.
--
http://mail.python.org/mailman/listinfo/python-list