Re: [Tutor] Modify inherited methods

2010-04-28 Thread Walter Wefft

Steven D'Aprano wrote:
 And for guru-level mastery, replace to call to dict.__init__ with ... 
nothing at all, because dict.__init__ doesn't do anything.





(Sorry, should have sent to list).

I don't understand this - it must do something:

class MyDict1(dict):

   def __init__(self, *args, **kw):
   pass

class MyDict2(dict):

   def __init__(self, *args, **kw):
   dict.__init__(self, *args, **kw)


d = MyDict1(y=2)
print d
{}

d = MyDict2(y=2)
print d
{'y': 2}

d = MyDict1({'x': 3})
print d
{}

d = MyDict2({'x': 3})
print d
{'x': 3}

Behaviour is different depending on whether you call the superclass 
__init__ or not.


?


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-28 Thread spir ☣
On Wed, 28 Apr 2010 07:53:06 +0100
Walter Wefft walterwe...@googlemail.com wrote:

 Steven D'Aprano wrote:
   And for guru-level mastery, replace to call to dict.__init__ with ... 
 nothing at all, because dict.__init__ doesn't do anything.
  
  
  
 
 (Sorry, should have sent to list).
 
 I don't understand this - it must do something:
 
 class MyDict1(dict):
 
 def __init__(self, *args, **kw):
 pass
 
 class MyDict2(dict):
 
 def __init__(self, *args, **kw):
 dict.__init__(self, *args, **kw)
 
 
 d = MyDict1(y=2)
 print d
 {}
 
 d = MyDict2(y=2)
 print d
 {'y': 2}
 
 d = MyDict1({'x': 3})
 print d
 {}
 
 d = MyDict2({'x': 3})
 print d
 {'x': 3}
 
 Behaviour is different depending on whether you call the superclass 
 __init__ or not.
 
 ?

Hem... this is a rather obscure point (I personly have it wrong each time I 
need to subtype builtin types). Maybe you find some enlightenment in the 
following code:

===
class MyDict0(dict):
pass
class MyDict1(dict):
def __init__(self, *args, **kw):
pass
class MyDict2(dict):
def __init__(self, *args, **kw):
dict.__init__(self, *args, **kw)
===

d0 = MyDict0(a=1) ; d1 = MyDict1(a=1) ; d2 = MyDict2(a=1)
print d0,d1,d2 # == {'a': 1} {} {'a': 1}

In case you do not define any custom __init__ *at all*, dict will transparently 
feed an instance of your type with provided entries, if any. If you define one, 
and don't feed the collection yourself, you need to call dict's __init__ to do 
it for you.
This behaviour allows having custom params at init:

===
class MyDict(dict):
def __init__(self, name=, **entries):
self.name = name
dict.__init__(self, **entries)
def __str__(self):
return %s:%s %(self.name,dict.__str__(self))
d = MyDict(name=XYZ, a=1,b=2,c=3)
print d # == XYZ:{'a': 1, 'c': 3, 'b': 2}
===

But all this does not apply to atomic builtin types such as int:

===
class MyInt0(int):
pass

class MyInt1(int):
def __init__(self, *args):
pass

class MyInt2(int):
def __init__(self, *args):
int.__init__(self, *args)

i0 = MyInt0(1) ; i1 = MyInt1(1) ; i2 = MyInt2(1)
print i0,i1,i2  # == 1 1 1
===

This runs by me with a message from the compiler: DeprecationWarning: 
object.__init__() takes no parameters (about the call to int.__init__).
I would like to understand the implementation and the reason for this 
difference.
This means one cannot customize the initialisation of a subtype of int like is 
done above for a subtype of dict:

===
class MyInt(int):
def __init__(self, value=0, name=):
self.name = name
int.__init__(self, value)
def __str__(self):
return %s:%s %(self.name,int.__str__(self))
#~ i = MyInt(name=XYZ, value=3)
i = MyInt(3, XYZ)
print i # == TypeError: an integer is required
===

(Keyword parameters will also be rejected.) This is due to the implicit 
execution of the builtin constructor, which requires definite parameters (here 
a value and possibly a base).
More info on this topic welcome :-)

Denis


vit esse estrany ☣

spir.wikidot.com
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-28 Thread Walter Wefft

spir ☣ wrote:

On Wed, 28 Apr 2010 07:53:06 +0100
Walter Wefft walterwe...@googlemail.com wrote:


Steven D'Aprano wrote:
  And for guru-level mastery, replace to call to dict.__init__ with ... 
nothing at all, because dict.__init__ doesn't do anything.

 
 
 

(Sorry, should have sent to list).

I don't understand this - it must do something:

class MyDict1(dict):

def __init__(self, *args, **kw):
pass

class MyDict2(dict):

def __init__(self, *args, **kw):
dict.__init__(self, *args, **kw)


d = MyDict1(y=2)
print d
{}

d = MyDict2(y=2)
print d
{'y': 2}

d = MyDict1({'x': 3})
print d
{}

d = MyDict2({'x': 3})
print d
{'x': 3}

Behaviour is different depending on whether you call the superclass 
__init__ or not.


?


Hem... this is a rather obscure point (I personly have it wrong each time I 
need to subtype builtin types). Maybe you find some enlightenment in the 
following code:

===
class MyDict0(dict):
pass
class MyDict1(dict):
def __init__(self, *args, **kw):
pass
class MyDict2(dict):
def __init__(self, *args, **kw):
dict.__init__(self, *args, **kw)
===

d0 = MyDict0(a=1) ; d1 = MyDict1(a=1) ; d2 = MyDict2(a=1)
print d0,d1,d2 # == {'a': 1} {} {'a': 1}



You reiterate my point. To say that dict.__init__ can be omitted in a 
subclass's __init__ with no effect, is not a correct statement.


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-28 Thread Steven D'Aprano
On Wed, 28 Apr 2010 04:53:06 pm Walter Wefft wrote:
 Steven D'Aprano wrote:
   And for guru-level mastery, replace to call to dict.__init__ with
   ...

 nothing at all, because dict.__init__ doesn't do anything.
[...]
 Behaviour is different depending on whether you call the superclass
 __init__ or not.

 ?

Fascinating... it seems that you are correct. Just goes to show, you can 
be programming in Python for well over a decade and still learn 
something new.

Believe it or not, I did test the behaviour before posting, but 
obviously my tests were faulty!


-- 
Steven D'Aprano
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-28 Thread Walter Wefft

Emile van Sebille wrote:

On 4/28/2010 3:20 AM Walter Wefft said...

spir ☣ wrote:

On Wed, 28 Apr 2010 07:53:06 +0100
Walter Wefft walterwe...@googlemail.com wrote:

snip

===
class MyDict0(dict):
pass
class MyDict1(dict):
def __init__(self, *args, **kw):
pass
class MyDict2(dict):
def __init__(self, *args, **kw):
dict.__init__(self, *args, **kw)
===

d0 = MyDict0(a=1) ; d1 = MyDict1(a=1) ; d2 = MyDict2(a=1)
print d0,d1,d2 # == {'a': 1} {} {'a': 1}



You reiterate my point. To say that dict.__init__ can be omitted in a
subclass's __init__ with no effect, is not a correct statement.



It wasn't the omitted case that exhibits the difference.  When 
sub-classing, any methods omitted defer to the parent's version so the 
init from the dict parent happened.




omitted in a subclass's __init__, ie. a *call* to the superclass's method

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-28 Thread Emile van Sebille

On 4/28/2010 9:32 AM Walter Wefft said...

Emile van Sebille wrote:

On 4/28/2010 3:20 AM Walter Wefft said...

You reiterate my point. To say that dict.__init__ can be omitted in a
subclass's __init__ with no effect, is not a correct statement.



It wasn't the omitted case that exhibits the difference. When
sub-classing, any methods omitted defer to the parent's version so the
init from the dict parent happened.



omitted in a subclass's __init__, ie. a *call* to the superclass's method



You're right.  Failure to read on my part.  Sorry.

Emile

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-28 Thread Eike Welk
On Wednesday April 28 2010 13:04:30 Steven D'Aprano wrote:
 On Wed, 28 Apr 2010 04:53:06 pm Walter Wefft wrote:
  Steven D'Aprano wrote:
And for guru-level mastery, replace to call to dict.__init__ with
...
 
  nothing at all, because dict.__init__ doesn't do anything.
 
 [...]
 
  Behaviour is different depending on whether you call the superclass
  __init__ or not.
 
  ?
 
 Fascinating... it seems that you are correct. Just goes to show, you can
 be programming in Python for well over a decade and still learn
 something new.

You probably thought of tuple, where __init__ really does nothing. Tuple 
instances are created by __new__.


Eike.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-28 Thread C M Caine
Thank you all. One tangentially related question: what does (self,
*args, **kwargs) actually mean? How does one reference variables given
to a function that accepts these inputs?

Colin
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-28 Thread Eike Welk
On Wednesday April 28 2010 20:57:27 C M Caine wrote:
 Thank you all. One tangentially related question: what does (self,
 *args, **kwargs) actually mean? How does one reference variables given
 to a function that accepts these inputs?

*args is a tuple containing the positional arguments; 
**kwargs is a dictionary which contains the keyword arguments. 

The stars before the variable names are the special syntax to handle arbitrary 
function arguments; you can use any variable names you want. You can use the 
syntax in a function call and in a function definition.

Here's an example session with Ipython:

In [5]: def foo(*args, **kwargs):
   ...: print args: , args
   ...: print kwargs: , kwargs
   ...:
   ...:

In [6]: foo(1, 2, 3)
args:  (1, 2, 3)
kwargs:  {}

In [7]: foo(1, 2, 3, a=4, b=5)
args:  (1, 2, 3)
kwargs:  {'a': 4, 'b': 5}

In [8]: foo( *(10, 11), **{p:20, q:21})
args:  (10, 11)
kwargs:  {'q': 21, 'p': 20}


Eike.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


[Tutor] Modify inherited methods

2010-04-27 Thread C M Caine
I'm writing a class that inherits the inbuilt dict class and want some
of my own code to run at initialisation, on the other hand, I still
want the original dict.__init__ function to run. Can I ask the class
to run the original __init__ and then my own function at
initialisation automatically? If so, how?

Regards,
Colin Caine
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-27 Thread Steven D'Aprano
On Wed, 28 Apr 2010 07:24:48 am C M Caine wrote:
 I'm writing a class that inherits the inbuilt dict class and want
 some of my own code to run at initialisation, on the other hand, I
 still want the original dict.__init__ function to run. Can I ask the
 class to run the original __init__ and then my own function at
 initialisation automatically? If so, how?

This is the general technique for calling the superclass' method:

class MyDict(dict):
def __init__(self, *args, **kwargs):
# Call the superclass method.
dict.__init__(self, *args, **kwargs)
# Perform my own initialisation code.
print Calling my init code...


For advanced usage, replace the call to dict.__init__ with a call to 
super:

super(MyDict, self).__init__(*args, **kwargs)

And for guru-level mastery, replace to call to dict.__init__ with ... 
nothing at all, because dict.__init__ doesn't do anything.

Some people argue that you must call dict.__init__ even though it 
doesn't do anything. Their reasoning is, some day its behaviour might 
change, and if you don't call it in your subclass, then your class may 
break. This is true, as far as it goes, but what they say is that if 
the behaviour of dict.__init__ changes, and you *do* call it, your 
class may still break. (This is why dict is unlikely to change any time 
soon.)




-- 
Steven D'Aprano
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-27 Thread Steven D'Aprano
On Wed, 28 Apr 2010 08:08:12 am Steven D'Aprano wrote:

 Some people argue that you must call dict.__init__ even though it
 doesn't do anything. Their reasoning is, some day its behaviour might
 change, and if you don't call it in your subclass, then your class
 may break. This is true, as far as it goes, but what they say is that
 if the behaviour of dict.__init__ changes, and you *do* call it, your
 class may still break. (This is why dict is unlikely to change any
 time soon.)

Oops, left out a word. I meant to say what they *don't* say is



-- 
Steven D'Aprano
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Modify inherited methods

2010-04-27 Thread Alan Gauld


Steven D'Aprano st...@pearwood.info wrote

On Wed, 28 Apr 2010 07:24:48 am C M Caine wrote:

I'm writing a class that inherits the inbuilt dict class and want
some of my own code to run at initialisation, on the other hand, I
still want the original dict.__init__ function to run. ...



This is the general technique for calling the superclass' method:

class MyDict(dict):
   def __init__(self, *args, **kwargs):
   # Call the superclass method.
   dict.__init__(self, *args, **kwargs)
   # Perform my own initialisation code.
   print Calling my init code...


And just to be clear that applies to any method not just __init__
Also you can do your intialisation before or after or both.
eg.

def __init__()
# do local pre processing(optional)
super().__init__(...)
#  do local post processing(optional)

Some people argue that you must call dict.__init__ even though it 
doesn't do anything. Their reasoning is, some day its behaviour might 
change, and if you don't call it in your subclass, then your class may 
break. 


I tend to argue for calling even if its a null call. Mainly because you 
sometimes don't know what the superclass does or doesn't do 
(eg you might not have access to the source) so its safer to call 
it...


the behaviour of dict.__init__ changes, and you *do* call it, your 
class may still break. 


... and if it breaks you at least have access to your own code to fix it...

But if you do have access to the superclass source then you can 
make an informed decision. In general I'm too lazy to go looking 
for it and just put the super call in :-)


HTH,


--
Alan Gauld
Author of the Learn to Program web site
http://www.alan-g.me.uk/

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor