Private functions and inheritance

2007-07-16 Thread Maciej Bliziński
Hello,

I've come across something that I don't quite understand about
Python's inheritance. Consider the following code snippet:

class A(object):
def call_bar(self): return self.bar()
def call___bar(self): return self.__bar()
def __bar(self): return A::__bar()
def bar(self): return A::bar()

class B(A):
def __bar(self): return B::__bar()
def bar(self): return B::bar()

b = B()
print calling B::call_bar():, b.call_bar()
print calling B::call___bar():, b.call___bar()

The result is:

calling B::call_bar(): B::bar()
calling B::call___bar(): A::__bar()

In the latter case, it calls the base class' implementation. It
probably goes along with Python's spec, but I found it surprising. I
don't want to expose the __bar() function outside, but on the other
hand i want to defer its implementation to a subclass. It seems like I
need to make it public, doesn't it?

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


Re: Private functions and inheritance

2007-07-16 Thread Bjoern Schliessmann
Maciej Blizi?ski wrote:

 calling B::call_bar(): B::bar()
 calling B::call___bar(): A::__bar()

(BTW, there is no :: operator in Python. It should be, e. g., 
B.bar().)

 In the latter case, it calls the base class' implementation. It
 probably goes along with Python's spec, but I found it surprising.

__-prepended names are dynamically mangled to include the class
name. Hence, B.__bar doesn't overwrite A.__bar in B.

 I don't want to expose the __bar() function outside,

In principle, you do. Always. Public or Private is just convention
in Python. Even __-prepended names can be accessed from outside.

Couldn't find it in the docs though. Quite inconcise.

Regards,


Björn

-- 
BOFH excuse #120:

we just switched to FDDI.

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


Re: Private functions and inheritance

2007-07-16 Thread Diez B. Roggisch
Maciej Bliziński wrote:

 Hello,
 
 I've come across something that I don't quite understand about
 Python's inheritance. Consider the following code snippet:
 
 class A(object):
 def call_bar(self): return self.bar()
 def call___bar(self): return self.__bar()
 def __bar(self): return A::__bar()
 def bar(self): return A::bar()
 
 class B(A):
 def __bar(self): return B::__bar()
 def bar(self): return B::bar()
 
 b = B()
 print calling B::call_bar():, b.call_bar()
 print calling B::call___bar():, b.call___bar()
 
 The result is:
 
 calling B::call_bar(): B::bar()
 calling B::call___bar(): A::__bar()
 
 In the latter case, it calls the base class' implementation. It
 probably goes along with Python's spec, but I found it surprising. I
 don't want to expose the __bar() function outside, but on the other
 hand i want to defer its implementation to a subclass. It seems like I
 need to make it public, doesn't it?

Yep. Just use a single underscore, and that's it. The reason why this
doesn't work as expected is that the name-mangling introduced by the
leading double underscores is purely a lexical scope based mechanism.

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

Re: Private functions and inheritance

2007-07-16 Thread Neil Cerutti
On 2007-07-16, Maciej Blizi?ski [EMAIL PROTECTED] wrote:
 Hello,

 I've come across something that I don't quite understand about
 Python's inheritance. Consider the following code snippet:

 class A(object):
 def call_bar(self): return self.bar()
 def call___bar(self): return self.__bar()
 def __bar(self): return A::__bar()
 def bar(self): return A::bar()

 class B(A):
 def __bar(self): return B::__bar()
 def bar(self): return B::bar()

 b = B()
 print calling B::call_bar():, b.call_bar()
 print calling B::call___bar():, b.call___bar()

 The result is:

 calling B::call_bar(): B::bar()
 calling B::call___bar(): A::__bar()

the __* naming convention for class private attributes is
intended to help ensure that attribute names of derived classes
cannot conflict with private attribute names in any base classes.
I.e., you should not use that naming convention when you *intend*
to override it in a derived class. If you do use the __* naming
convention, use it only for attributes that should not be
overrided or accessed by derived classes.

the weasel words from the documentation (which I put in quotes)
are there because the feature doesn't work (in all cases).

-- 
Neil Cerutti
The doctors X-rayed my head and found nothing. --Dizzy Dean
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Private functions and inheritance

2007-07-16 Thread Bruno Desthuilliers
Maciej Bliziński a écrit :
(snip the rest - already answered by at least 3 persons).

 I
 don't want to expose the __bar() function outside, but on the other
 hand i want to defer its implementation to a subclass. It seems like I
 need to make it public, doesn't it?

First, keep in mind that that Python *does not* have any notion of 
(languaged enforced) access restriction. All that the  __name thingie 
does is to mangle the name with the class name, so A.bar become 
A._A__bar. This can be useful. Sometimes. Perhaps. (FWIW, I think I've 
used it once in seven years and I'm not sure it was really necessary 
after all).

Now there's a strong convention which says that _names prefixed by a 
single underscore are implementation stuff, and that anyone messing with 
implementation stuff implicitely accepts all the possible consequences.


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