473,320 Members | 1,977 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,320 software developers and data experts.

Instances behaviour

Hi all,
I've been using Python for 3 years, but I've rarely used its OOP
features (I'm a physicist, sorry). Now, after having read a lot about
Python OOP capabilities, I'm trying to get advantage of this (for me)
new paradigm. As a result I've a lot of somewhat philosophical
questions. I will start with one of them.

Suppose I have a bunch of classes that represent slightly (but
conceptually) different object. The instances of each class must behave
in very similar manner, so that I've created a common class ancestor
(let say A) that define a lot of special method (such as __getattr__,
__setattr__, __len__ and so on), and then I've created all my "real"
classes inheriting from it:
class A(object): ..... # here define all special and some common methods
class B(A): ..... # this is the first "real" class
class C(A):

..... # and this is the second

and so on. The problem I'm worried about is that an unaware user may
create an instance of "A" supposing that it has any real use, while it
is only a sort of prototype. However, I can't see (from my limited
point of view) any other way to rearrange things and still get a
similar behaviour.

Implementing those special methods directly in class B and then inherit
from it, doesn't seem the right way, since I'd prefer that instances of
B weren't in any relation with the instances of C (i.e. I'd prefer not
to subclass C from B)

Perhaps some OOP techniques (that I miss at the moment) could be of any
help. Any suggestion?

Thanks in advance,
Andrea.

Dec 2 '05 #1
10 1055
On Thu, Dec 01, 2005 at 03:51:05PM -0800, Mr.Rech wrote:
[...]
Suppose I have a bunch of classes that represent slightly (but
conceptually) different object. The instances of each class must behave
in very similar manner, so that I've created a common class ancestor
(let say A) that define a lot of special method (such as __getattr__,
__setattr__, __len__ and so on), and then I've created all my "real"
classes inheriting from it:
class A(object): .... # here define all special and some common methods
class B(A): .... # this is the first "real" class
class C(A): .... # and this is the second

and so on. The problem I'm worried about is that an unaware user may
create an instance of "A" supposing that it has any real use, while it
is only a sort of prototype. However, I can't see (from my limited
point of view) any other way to rearrange things and still get a
similar behaviour.

class A(object):
... def __init__(self, foo):
... if self.__class__ is A:
... raise TypeError("A is base class.")
... self.foo = foo
...
class B(A): .... pass
.... class C(A): .... def __init__(self, foo, bar):
.... A.__init__(self, foo)
.... self.bar = bar
.... a = A(1) Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 4, in __init__
TypeError: A is base class. b = B(1)
b.foo 1 c = C(1, 2)
c.foo, c.bar (1, 2)


HTH
--Inyeol Lee
Dec 2 '05 #2
"Mr.Rech" <an*************@gmail.com> writes:
Suppose I have a bunch of classes that represent slightly (but
conceptually) different object. The instances of each class must behave
in very similar manner, so that I've created a common class ancestor
(let say A) that define a lot of special method (such as __getattr__,
__setattr__, __len__ and so on), and then I've created all my "real"
classes inheriting from it:

and so on. The problem I'm worried about is that an unaware user may
create an instance of "A" supposing that it has any real use, while it
is only a sort of prototype. However, I can't see (from my limited
point of view) any other way to rearrange things and still get a
similar behaviour.

Perhaps some OOP techniques (that I miss at the moment) could be of any
help. Any suggestion?


I assume there are methods of B & C that aren't shared, and hence
aren't in A. When the user invokes those, they should get an error
message. That's how this kind of thing is normally dealt with.

If you want things to happen at instantiation time, then you can make
A.__init__ raise an exception. Your B & C __init__ then can't invoke
it. If A.__init__ has a real use, move that into another method that B
& C's __init__ can invoke.

<mike
--
Mike Meyer <mw*@mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
Dec 2 '05 #3
Mr.Rech wrote:
Suppose I have a bunch of classes that represent slightly (but
conceptually) different object. The instances of each class must behave
in very similar manner, so that I've created a common class ancestor
(let say A) that define a lot of special method (such as __getattr__,
__setattr__, __len__ and so on), and then I've created all my "real"
classes inheriting from it:
class A(object): ....*****#*here*define*all*special*and*some*common *methods
class B(A): ....****#*this*is*the*first*"real"*class
class C(A): ....****#*and*this*is*the*second

and so on. The problem I'm worried about is that an unaware user may
create an instance of "A" supposing that it has any real use, while it
is only a sort of prototype. However, I can't see (from my limited
point of view) any other way to rearrange things and still get a
similar behaviour.

Implementing those special methods directly in class B and then inherit
from it, doesn't seem the right way, since I'd prefer that instances of
B weren't in any relation with the instances of C (i.e. I'd prefer not
to subclass C from B)

Perhaps some OOP techniques (that I miss at the moment) could be of any
help. Any suggestion?


How about

class A(object):
"""Provides common functionality for A-like classes, e. g. B and C.

Do not instantiate.
"""

This is definitely a low-tech approach, but I suppose you don't clutter your
functions with spurious argument type checks, either.
An exception like the one shown by Inyeol Lee is typically raised once
during the development process while my approach bites (only) the
illiterate programmer with a message like
a.foo()

Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'A' object has no attribute 'foo'

which normally can be tracked down almost as quickly -- and which serves him
well anyway :-)

Peter

Dec 2 '05 #4
Inyeol Lee wrote:
(snip)
class A(object):
... def __init__(self, foo):
... if self.__class__ is A:
... raise TypeError("A is base class.")

s/TypeError/NotImplementedError/
s/base class/abstract class/
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Dec 2 '05 #5
Thanks for your suggestions. They are very usefull and indeed bypass my
problem. However, I've found a (perhaps) more elegant way to get the
same result using metaclasses. My idea is to define my classes as
follows:
class meta_A(type): ..... def __new__(cls, classname, bases, classdict):
# define here all special methods
newdict = { #special methods dict}
classdict.update(newdict) # any suggestion on
automatically build newdict?
return type.__new__(cls, classname, bases, classdict)
class B(object):

__metaclass__ = meta_A
# More methods here

I know metaclasses are a complete different beast, anyway I find this
approach more pythonic. Any comment? Suggestion?

Thanks,
Andrea.

Dec 2 '05 #6
Mr.Rech wrote:
Thanks for your suggestions. They are very usefull and indeed bypass my
problem. However, I've found a (perhaps) more elegant way to get the
same result using metaclasses. My idea is to define my classes as
follows:
class meta_A(type): .... def __new__(cls, classname, bases, classdict):
# define here all special methods
newdict = { #special methods dict}
classdict.update(newdict) # any suggestion on
automatically build newdict?
return type.__new__(cls, classname, bases, classdict)


Are you intentionally defeating inheritance?
class B(object):

__metaclass__ = meta_A
# More methods here

I know metaclasses are a complete different beast, anyway I find this
approach more pythonic. Any comment? Suggestion?


Godawful.

Don't use classes when functions suffice.
Don't use inheritance when duck-typing suffices.
Don't use metaclasses when inheritance suffices.
Corollary: don't use metaclasses to solve problems you have just made up.

In short, the simplest solution is most likely the most pythonic, even when
some odd corner cases are not covered.

Simplicity also has a nice side effect: fewer bugs.

Peter

Dec 2 '05 #7
Mr.Rech wrote:
Thanks for your suggestions. They are very usefull and indeed bypass my
problem. However, I've found a (perhaps) more elegant way to get the
same result using metaclasses.

(snip code)
I know metaclasses are a complete different beast, anyway I find this
approach more pythonic.


It's not. It's a case of ArbitraryOvercomplexification(tm).

The pythonic way is to use inheritence and make the base class abstract
by raising a NotImplementedError in it's __init__ (cf Inyeol Lee's
answer and my small correction)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Dec 2 '05 #8
I see your point. Looking again at my metaclass implementation and
comparing it with your abstract class + inheritance approach it turns
out that the latter is definetively more straightforward, easier to
maintain and all in all more pythonic.

Sorry, but being an OOP newbie put me in the position of
overcomplexifing(tm) things a little bit. I'll be back soon with other
(I hope less silly) questions. ;-p

Thanks for all your suggestions,
Andrea

Dec 2 '05 #9
On Fri, Dec 02, 2005 at 10:43:56AM +0100, bruno at modulix wrote:
Inyeol Lee wrote:
(snip)
>class A(object):
>... def __init__(self, foo):
>... if self.__class__ is A:
>... raise TypeError("A is base class.")

s/TypeError/NotImplementedError/
s/base class/abstract class/


I prefer TypeError here, NotImplementedError would be OK though.
Here is an example from sets.py in stdlib.
class BaseSet(object):
"""Common base class for mutable and immutable sets."""

__slots__ = ['_data']

# Constructor

def __init__(self):
"""This is an abstract class."""
# Don't call this from a concrete subclass!
if self.__class__ is BaseSet:
raise TypeError, ("BaseSet is an abstract class. "
"Use Set or ImmutableSet.")
Inyeol
Dec 2 '05 #10
Mr.Rech wrote:
and so on. The problem I'm worried about is that an unaware user may
create an instance of "A" supposing that it has any real use, while it
is only a sort of prototype. However, I can't see (from my limited
point of view) any other way to rearrange things and still get a
similar behaviour.

1) Document your class is not intended for public use.
2) Make your A class "private" of the module that defines it. A simple way is
putting an underscore in front of its name.
3) Make your A class non-functional. I assume B and C have methods that A
doesn't. Then, add those methods to A too, but not implement them:

def foo(self):
"""Foo this and that. Must be implemented in subclasses."""
raise NotImplementedError

--
Giovanni Bajo
Dec 4 '05 #11

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

Similar topics

4
by: Klaus Neuner | last post by:
Hello, code (1) works, code (2) doesn't. (1) data = cgi.FieldStorage() comment = data.getvalue("comment") user_name = data.getvalue("user_name") (2)
1
by: Vidyaranya | last post by:
I am facing one problem w.r.t DB2, When i launch my first instance of my client exe. (written using Delphi 7) and perform an action on Table A. (one of the row is in Transaction mode) waits for...
22
by: Ben Finney | last post by:
Howdy all, I've recently packaged 'enum' in PyPI. In its description, I make the claim that it creates "immutable" enumeration objects, and that the enumeration values are "constant" values. ...
90
by: Ben Finney | last post by:
Howdy all, How can a (user-defined) class ensure that its instances are immutable, like an int or a tuple, without inheriting from those types? What caveats should be observed in making...
8
by: quortex | last post by:
Hi all, I have a native class which has a single instance controlled via the singleton pattern. I need to call this from both native C++ and from mixed mode visual studio 2005 c++ CLI. At...
2
by: jantod | last post by:
I not only want to compare class *instances* but also the classes themselves. Something like: class T(object): @classmethod def __cmp__(cls, other): return cmp(cls.__name__, other.__name__)...
4
by: Pedro Werneck | last post by:
Hi all I noticed something strange here while explaining decorators to someone. Not any real use code, but I think it's worth mentioning. When I access a class attribute, on a class with a...
7
by: Ben | last post by:
Hello... I have a dictionary, where each value is a seperate instance of the same class: self.mop_list=record(self.mops) In my case I know that record_number takes the values 0,3,and 7...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
1
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: 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)...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
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.