473,325 Members | 2,342 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,325 software developers and data experts.

Name conflict in class hierarchy

I believe that the answer to my question is no, but I want to be sure that I
understand this issue correctly: Suppose that there are two classes
defined as follows:

class A(object):
def f1(self):
print 'In A.f1, calling func'
self.func()

def func(self):
print 'In A.func'

class B(A):
def func(self):
print 'In B.func, calling A.f1'
A.f1(self)

Class A was defined by someone else or it comes from a library, so I have no
prior information about what is in it. I subclass A to add some new
functionality, and I call the new function "func". The function B.func
uses A.f1, but unbeknownst to me, A.f1 uses A.func. Unfortunately, class B
overrides func, so the call in A.f1 to self.func actually invokes B.func,
resulting in this case in an infinite loop. Is there a way from B to
specify that A should use its own version of func and ignore the version in
B? I know that I could rename A.func to avoid the name clash, but since A
is actually in a library, I will lose that change when I upgrade the
library. I could rename B.func, but there is already a bunch of code that
calls it so I would have to update all the calls. That seems like the
correct solution, though. The other possibility is to use composition
rather than subclassing:

class B:
def func(self):
print 'In B.func, calling A.f1'
a = A()
a.f1()

but then B does not inherit other functions of A that I would like to use.
It struck me that this must be a common problem in OOP, so I'm wondering
whether there is a simple solution that I am missing.
--
Jeffrey Barish

May 21 '06 #1
8 1728
Jeffrey Barish wrote:
I believe that the answer to my question is no, but I want to be sure that I
understand this issue correctly: Suppose that there are two classes
defined as follows:

class A(object):
def f1(self):
print 'In A.f1, calling func'
self.func()

def func(self):
print 'In A.func'

class B(A):
def func(self):
print 'In B.func, calling A.f1'
A.f1(self)

Class A was defined by someone else or it comes from a library, so I have no
prior information about what is in it. I subclass A to add some new
functionality, and I call the new function "func". The function B.func
uses A.f1, but unbeknownst to me, A.f1 uses A.func. Unfortunately, class B
overrides func, so the call in A.f1 to self.func actually invokes B.func,
resulting in this case in an infinite loop. Is there a way from B to
specify that A should use its own version of func and ignore the version in
B? I know that I could rename A.func to avoid the name clash, but since A
is actually in a library, I will lose that change when I upgrade the
library. I could rename B.func, but there is already a bunch of code that
calls it so I would have to update all the calls. That seems like the
correct solution, though. The other possibility is to use composition
rather than subclassing:

class B:
def func(self):
print 'In B.func, calling A.f1'
a = A()
a.f1()

but then B does not inherit other functions of A that I would like to use.
It struck me that this must be a common problem in OOP, so I'm wondering
whether there is a simple solution that I am missing.


When you subclass an object it is your responsibility to check to make sure
you don't override existing methods in that class unintentionally. Of course
you may want to intentionally override the methods so as to replace them with
your own methods. You are correct, renaming A.func wouldn't be a good idea.
A good editor should make changing all the calls to B.func not be all that
hard.

You can easily get information about the methods by doing an import and dir().

Example:
import ConfigParser
dir(ConfigParser) ['ConfigParser', 'DEFAULTSECT', 'DuplicateSectionError', 'Error',
'InterpolationDepthError', 'InterpolationError',
'InterpolationMissingOptionError', 'InterpolationSyntaxError',
'MAX_INTERPOLATION_DEPTH', 'MissingSectionHeaderError', 'NoOptionError',
'NoSectionError', 'ParsingError', 'RawConfigParser', 'SafeConfigParser',
'__all__', '__builtins__', '__doc__', '__file__', '__name__', 're']
Depending on the author, you may also be able to get extensive help
on all the methods with help().
help(ConfigParser)

Help on module ConfigParser:

NAME
ConfigParser - Configuration file parser.

FILE
c:\python24\lib\configparser.py

DESCRIPTION
A setup file consists of sections, lead by a "[section]" header,
and followed by "name: value" entries, with continuations and such in
the style of RFC 822.
-Larry Bates
May 21 '06 #2
Jeffrey Barish wrote:

[overriding of base class member functions by subclass]
but then B does not inherit other functions of A that I would like to use.
It struck me that this must be a common problem in OOP, so I'm wondering
whether there is a simple solution that I am missing.


In C++, one has virtual member functions (which behave like python's),
and their purpose is to be overriden (o.g. a print method, whose subclass
version will print more attributes than the base knows about).

Such functions usually are documented - otherwise their being virtual
would make no sense.

In Python, a function not intended to be overriden should be either
have a name starting with an underscore or be documented. So the person
who should change something is the author of the library, not you.

In your current situation, the following options seem to remain:

1. Use funny names ("foobar239847562384756" instead of "func")
and hope that the library update will not use them

2. Call dir(classname) at hacking time and avoid names listed
therein. This breaks if the library update may happen at the
user's site without you being able to change your code.

3. Call dir(classname) at runtime and raise an exception
if it contains a name used by you.

Ralf
May 21 '06 #3
Jeffrey Barish wrote:
Suppose that there are two classes defined as follows:

class A(object):
def f1(self):
print 'In A.f1, calling func'
self.func()

def func(self):
print 'In A.func'

class B(A):
def func(self):
print 'In B.func, calling A.f1'
A.f1(self)

Class A was defined by someone else or it comes from a library, so I have no
prior information about what is in it. I subclass A to add some new
functionality, and I call the new function "func". The function B.func
uses A.f1, but unbeknownst to me, A.f1 uses A.func. Unfortunately, class B
overrides func, so the call in A.f1 to self.func actually invokes B.func,
resulting in this case in an infinite loop. Is there a way from B to
specify that A should use its own version of func and ignore the version in
B? I know that I could rename A.func to avoid the name clash, but since A
is actually in a library, I will lose that change when I upgrade the
library. I could rename B.func, but there is already a bunch of code that
calls it so I would have to update all the calls. That seems like the
correct solution, though. The other possibility is to use composition
rather than subclassing:

class B:
def func(self):
print 'In B.func, calling A.f1'
a = A()
a.f1()

but then B does not inherit other functions of A that I would like to use.
It struck me that this must be a common problem in OOP, so I'm wondering
whether there is a simple solution that I am missing.


If you insist on this (I find silly) version, I'd suggest you want
to use "has-a" rather than "is-a" relationship between B and A

class A(object):
def f1(self):
print 'In A.f1, calling func'
self.func()

def func(self):
print 'In A.func'

class B(object):
def __init__(self, *args, **kwargs):
self._a = A(*args, **kwargs)

def func(self):
print 'In B.func, calling A.f1'
self._a.f1()
But, you could use this (I think ill-advised) technique if you
need a special-case work-around:

class Bb(A):
def __init__(self, *args, **kwargs):
super(Bb, self).__init__(*args, **kwargs)
self._recursed_func = 0

def f1(self):
self._recursed_func += 1
try:
return super(Bb, self).f1()
finally:
self._recursed_func -= 1

def func(self):
if self._recursed_func:
return super(Bb, self).func()
print 'In B.func, calling A.f1'
self.f1()
--Scott David Daniels
sc***********@acm.org
May 21 '06 #4
Ralf Muschall wrote:
Jeffrey Barish wrote:

[overriding of base class member functions by subclass]
(snip)
In Python, a function not intended to be overriden should be either
have a name starting with an underscore
actually with *two* underscores. The single-leading-underscore naming
scheme is the convention for 'protected' (read: 'implementation, not
API') attributes.
or be documented.


s/or/and/
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
May 22 '06 #5
bruno at modulix wrote:
Ralf Muschall wrote:
Jeffrey Barish wrote:

[overriding of base class member functions by subclass] ....
In Python, a function not intended to be overriden should be either
have a name starting with an underscore


actually with *two* underscores. The single-leading-underscore naming
scheme is the convention for 'protected' (read: 'implementation, not
API') attributes.


The double-underscore is there to generate names that are unlikely to
accidentally conflict. Use for anything else simply annoys those of
us who may need to get access to those instances and methods.

--
--Scott David Daniels
sc***********@acm.org
May 22 '06 #6
bruno at modulix wrote:
In Python, a function not intended to be overriden should be either
have a name starting with an underscore
actually with *two* underscores. The single-leading-underscore naming
scheme is the convention for 'protected' (read: 'implementation, not
API') attributes.


That's what I meant. "A.func" looked like an internal implementation
detail.
or be documented.


Having the implementation details documented too would be nice, but
hardly enforceable in real life.

Ralf
May 23 '06 #7
Jeffrey Barish wrote:
I believe that the answer to my question is no, but I want to be sure that I
understand this issue correctly: Suppose that there are two classes
defined as follows:

class A(object):
def f1(self):
print 'In A.f1, calling func'
self.func()

def func(self):
print 'In A.func'

class B(A):
def func(self):
print 'In B.func, calling A.f1'
A.f1(self)

Class A was defined by someone else or it comes from a library, so I have no
prior information about what is in it. I subclass A to add some new
functionality, and I call the new function "func". The function B.func
uses A.f1, but unbeknownst to me, A.f1 uses A.func. Unfortunately, class B
overrides func, so the call in A.f1 to self.func actually invokes B.func,
resulting in this case in an infinite loop. Is there a way from B to
specify that A should use its own version of func and ignore the version in
B? I know that I could rename A.func to avoid the name clash, but since A
is actually in a library, I will lose that change when I upgrade the
library. I could rename B.func, but there is already a bunch of code that
calls it so I would have to update all the calls. That seems like the
correct solution, though. The other possibility is to use composition
rather than subclassing:

class B:
def func(self):
print 'In B.func, calling A.f1'
a = A()
a.f1()

but then B does not inherit other functions of A that I would like to use.
It struck me that this must be a common problem in OOP, so I'm wondering
whether there is a simple solution that I am missing.


I was bitten by the same issue the first time I used Zope :-(
This is my solution, a metaclass that warns you if you try to override
an attribute defined in some ancestor:

class Base(object):
func = 1

class check_if_we_are_overriding_names(type):
def __new__(mcl, name, bases, dic):
for name, val in dic.iteritems():
if name.endswith("__"): continue
if sum(hasattr(base, name) for base in bases):
print "AlreadyDefinedNameWarning:", name
return super(check_if_we_are_overriding_names, mcl).__new__(
mcl, name, bases, dic)

class MyClass(Base):
__metaclass__ = check_if_we_are_overriding_names
func = 2 # you will get a warning at this point
Michele Simionato

May 23 '06 #8
Scott David Daniels wrote:
bruno at modulix wrote:
Ralf Muschall wrote:
Jeffrey Barish wrote:

[overriding of base class member functions by subclass] ....
In Python, a function not intended to be overriden should be either
have a name starting with an underscore

actually with *two* underscores. The single-leading-underscore naming
scheme is the convention for 'protected' (read: 'implementation, not
API') attributes.

The double-underscore is there to generate names that are unlikely to
accidentally conflict.


Yes, I do know this, and uses it when appropriate (that is : almost never)

I was just correcting Ralf's wrong statement about the single leading
underscore convention meant to denote "functions not intended to be
overriden".

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
May 23 '06 #9

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

Similar topics

2
by: Matt | last post by:
Hello, I would like to generate what I call an "overall class hierarchy" in UML automatically derived from my C++ code source. An example of what I seek: ...
9
by: John | last post by:
I am using two large libraries which both have an implementation of a "matrix" class. I have the source code for both. I need to use them in the same project and when I try to compile I get a...
3
by: CsaaGuy | last post by:
Hi, i created a class that i have showing up at design time and i have to save some of the properties to the viewstate at runtime. It all works fine, however the issue is if i have more that one...
2
by: Whywhat | last post by:
Hi! I have a name conflict between my class and windows.h header. The problem is because of windows.h contains GetMessage macro and my class a method with the same name. Thus the macro replaces...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...

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.