By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,199 Members | 1,125 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,199 IT Pros & Developers. It's quick & easy.

How to tell which subclass was used to instantiate object

P: n/a
Hi all

I have a question regarding inheritance. I have come up with a
solution, but it is not very elegant - I am sure there is a more
pythonic approach. Assume the following class definitions.

class Table:
def __init__(self,table_name,table_type):

class Master(Table):
def __init__(self,table_name,table_type):
Table.__init__(self,table_name,table_type)

class Transaction(Table):
def __init__(self,table_name,table_type):
Table.__init__(self,table_name,table_type)

class Armaster(Master):
def __init__(self,table_name,table_type):
Master.__init__(self,table_name,table_type)

Table is the main class, which represents a database table. Master is
a subclass that encapsulates various common characteristics of a
'master file' type of table. Transaction is a subclass that
encapsulates various common characteristics of a 'transaction file'
type of table. ArMaster is a subclass that is created to handle
specific requirements for the ArMaster table, which is a 'master file'
type of table.

Both of the following would be errors -

class Armaster(Table):
def __init__(self,table_name,table_type):
Table.__init__(self,table_name,table_type)

class Armaster(Transaction):
def __init__(self,table_name,table_type):
Transaction.__init__(self,table_name,table_type)

By inheriting from the incorrect class, the special methods to handle
a 'Master' type table have been bypassed. My question is, how can
Table check that objects have inherited from the correct subclasses?

Here is my inelegant solution. Assume that table_type contains the
string 'Master'.

class Master(Table):
def __init__(self,table_name,table_type):
self.my_type = 'Master'
Table.__init__(self,table_name,table_type)

class Table:
def __init__(self,table_name,table_type):
if hasattr(self,'my_type'):
ok = (self.my_type == table_type)
else:
ok = False
if not ok:
raise RuntimeError('%s must be of type %s' %
(table_name,table_type))

Is there a more direct way for a top-level class to determine which
subclasses were used to instantiate it?

Thanks

Frank Millman
Jul 18 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a

"Frank Millman" <fr***@chagford.com> wrote in message
news:24**************************@posting.google.c om...
Hi all

I have a question regarding inheritance. I have come up with a
solution, but it is not very elegant - I am sure there is a more
pythonic approach. Assume the following class definitions.
[...]
Is there a more direct way for a top-level class to determine which
subclasses were used to instantiate it?
Look at the __class__ attribute. Specifically, __class__.__name__
should tell you the name of the class.

John Roth
Thanks

Frank Millman

Jul 18 '05 #2

P: n/a
On 1 May 2004 05:47:20 -0700,
fr***@chagford.com (Frank Millman) wrote:

[ details of a multi-level object hierarchy, and worries of __init__
methods bypassing it ]
By inheriting from the incorrect class, the special methods to
handle a 'Master' type table have been bypassed. My question is,
how can Table check that objects have inherited from the correct
subclasses?
Python usually takes the "we're all adults here" point of view,
and leaves that question to unit tests and/or code reviews. No
amount of B&D is sufficient to protect from a malicious coder
anyway.
Here is my inelegant solution. Assume that table_type contains
the string 'Master'. class Master(Table):
def __init__(self,table_name,table_type):
self.my_type = 'Master'
Table.__init__(self,table_name,table_type) class Table:
def __init__(self,table_name,table_type):
if hasattr(self,'my_type'):
ok = (self.my_type == table_type)
else:
ok = False
if not ok:
raise RuntimeError('%s must be of type %s' %
(table_name,table_type)) Is there a more direct way for a top-level class to determine
which subclasses were used to instantiate it?


You could add another (optional) parameter to Table.__init__, but
that's really the same solution with new syntactic sugar.

You could unwind the stack frame and look at who's calling
Table.__init__, but that's rather un-Pythonic, too.

IMO, the most Pythonic solution is to provide factory functions
that do the Right Thing instead of instantiating your classes
directly from your application code.

HTH,
Heather

--
Heather Coppersmith
That's not right; that's not even wrong. -- Wolfgang Pauli
Jul 18 '05 #3

P: n/a
"John Roth" <ne********@jhrothjr.com> wrote in message news:<10*************@news.supernews.com>...
"Frank Millman" <fr***@chagford.com> wrote in message
news:24**************************@posting.google.c om...
Hi all

I have a question regarding inheritance. I have come up with a
solution, but it is not very elegant - I am sure there is a more
pythonic approach. Assume the following class definitions.

[...]

Is there a more direct way for a top-level class to determine which
subclasses were used to instantiate it?


Look at the __class__ attribute. Specifically, __class__.__name__
should tell you the name of the class.

John Roth


Thanks for the reply, John. Unfortunately this does not seem to give
me what I am looking for. I can only look at the __class__ attribute
once the object has been instantiated.

I want to check the inheritance hierarchy from the top-level __init__
while the object is being instantiated, and raise an exception if it
fails my test.

It seems from Heather's reply that it is not possible to do this
directly, and therefore my inelegant solution is probably as good as
any. See my reply to Heather for further comments.

Thanks again.

Frank
Jul 18 '05 #4

P: n/a
Heather Coppersmith <me@privacy.net> wrote in message news:<m2************@unique.phony.fqdn>...
On 1 May 2004 05:47:20 -0700,
fr***@chagford.com (Frank Millman) wrote:

[ details of a multi-level object hierarchy, and worries of __init__
methods bypassing it ]
By inheriting from the incorrect class, the special methods to
handle a 'Master' type table have been bypassed. My question is,
how can Table check that objects have inherited from the correct
subclasses?
Python usually takes the "we're all adults here" point of view,
and leaves that question to unit tests and/or code reviews. No
amount of B&D is sufficient to protect from a malicious coder
anyway.


I fully agree, but this is not the scenario I am trying to cater for.
I will explain what I am doing - maybe you can suggest a better
approach.

I am writing a general-purpose accounting/business package. It is the
nature of such beasts that no matter how powerful/generalised it is,
certain users will always have special requirements. I am therefore
including a large number of 'hooks' where users or their consultants
can add their own code without interfering with the main body of code.
One example of this is adding features to a particular database table
definition.

I have a standard class definition to represent a table, with various
attributes and methods. I allow the user to create their own subclass
for a particular table, adding/overriding where necessary. I have a
function to 'open' a table. This uses a try/except to 'try' to import
and instantiate a subclass for the table, 'except' instantiate the
standard class.

I have recently introduced the concept of a 'table type', such as
'Master' or 'Transaction', and have written my own subclasses with
standard methods to handle each type of table. The table type is
passed as an argument to the 'open' function. which now checks for a
user-defined subclass first, if not found checks the type to see if a
standard subclass exists, if not found instantiates the main class.
This works well.

The concern is that a table may be of type Master, but a user may
create their own subclass and inherit from Table instead of Master by
mistake. I want to detect this error and raise an exception.

You could unwind the stack frame and look at who's calling
Table.__init__, but that's rather un-Pythonic, too.
I do not know what this means, and I really do not want to know :-)
IMO, the most Pythonic solution is to provide factory functions
that do the Right Thing instead of instantiating your classes
directly from your application code.

If you can give a simple example, I would be interested in learning
more about this. Alternatively, I will leave things as they are for
now, and focus on getting my app to a point where I can get some live
installations. If things look promising, I will release it as Open
Source, and then I will be very happy to get feedback on this and, I
am sure, many other aspects of my coding that could be substantially
improved.
HTH,
Heather


Many thanks for your input.

Frank

ps What does B&D mean?
Jul 18 '05 #5

P: n/a
Frank Millman wrote:
I have recently introduced the concept of a 'table type', such as
'Master' or 'Transaction', and have written my own subclasses with
standard methods to handle each type of table. The table type is
passed as an argument to the 'open' function. which now checks for a
user-defined subclass first, if not found checks the type to see if a
standard subclass exists, if not found instantiates the main class.
This works well.

The concern is that a table may be of type Master, but a user may
create their own subclass and inherit from Table instead of Master by
mistake. I want to detect this error and raise an exception.


How about providing a subclass for every table the user might want to
subclass:

class Table:
def __init__(self, name=None):
if name is None:
try:
name = self.name
except AttributeError:
name = self.__class__.__name__
self.name = name

class Master(Table):
pass

class Transaction(Table):
pass

# provide a suggestively named class for every table in your application
class Employees(Table): pass
class Departments(Master): pass
class Invoices(Transaction):
name = "not-a-legal-identifier"
for cls in [Employees, Departments, Invoices]:
print cls().name
Now the user can just subclass Employees without having to care whether it
has to be derived from Transaction, Master, Table or whatever.
If he needs to know, he can discover it on the command line:
issubclass(Employees, Transaction) False issubclass(Invoices, Transaction) True


An additional benefit is that user code is shielded to some extent from
modifications in your code, e. g., you could later change the base of
Employees from Table to Master without requiring changes in client code.

Peter

Jul 18 '05 #6

P: n/a

"Frank Millman" <fr***@chagford.com> wrote in message
news:24**************************@posting.google.c om...
Heather Coppersmith <me@privacy.net> wrote in message news:<m2************@unique.phony.fqdn>...
Python usually takes the "we're all adults here" point of view,
and leaves that question to unit tests and/or code reviews. No
amount of B&D is sufficient to protect from a malicious coder
anyway.

ps What does B&D mean?


Bondage and Discipline


Jul 18 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.