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

Question about isinstance()

Hi all,
I've read some thread about isinstance(), why it is considered harmful
and how you can achieve the same results using a coding style that
doesn't break polymorphism etc... Since I'm trying to improve my Python
knowledge, and I'm going to design a class hierarchy from scratch, I'd
like to have some feedback about this from those of you much more
experienced than me in OOP.

Suppose I'm writing a base class with an __eq__ special methods, using
isinstance() I would have wrote:

class foo(object):
...
def __eq__(self, other):
return isinstance(other, type(self)) and self.an_attribute ==
other.an__attribute

Now, avoiding isinstace() I've written the following code:

class foo(object):
...
def __eq__(self, other):
try:
return self.an_attribute == other.an_attribute
except AttributeError:
return False

Any better way to write this method? Any suggestion?

Jan 26 '06 #1
19 1888
Mr.Rech:
Now, avoiding isinstace() I've written the following code:

class foo(object):
...
def __eq__(self, other):
try:
return self.an_attribute == other.an_attribute
except AttributeError:
return False


This may give unexpected results when you compare a foo with an instance
of a completely different type that happens to have an attribute called
'an_attribute'.

--
René Pijlman

Wat wil jij worden? http://www.carrieretijger.nl
Jan 26 '06 #2
Mmm... I've not considered such an event... Would you say it is one of
those rare case in which isinstance() "can be used"? Any other
suggestion?

Thanks,
Andrea

Jan 26 '06 #3
On Thu, 26 Jan 2006, Mr.Rech wrote:
I've read some thread about isinstance(), why it is considered harmful
and how you can achieve the same results using a coding style that
doesn't break polymorphism etc... Since I'm trying to improve my Python
knowledge, and I'm going to design a class hierarchy from scratch, I'd
like to have some feedback about this from those of you much more
experienced than me in OOP.
When trying to write OO code, you should of course always be suspicious of
any use of "isinstance". However, it is not always "considered harmful",
and this is one case where it is perfectly reasonable.
Now, avoiding isinstace() I've written the following code:

class foo(object):
...
def __eq__(self, other):
try:
return self.an_attribute == other.an_attribute
except AttributeError:
return False


You were better off with what you had before. Equality in this case is
left completely open-ended, and as a result, there is no way that you can
guarantee that "a == b" is the same as "b == a" if "a" is a "foo" and "b"
is of unknown type. This can lead to bizarre and unpredictable behavior.

--
.:[ dave benjamin -( ramen/sp00 )- http://spoomusic.com/ ]:.

"To attain knowledge, add things every day.
To attain wisdom, remove things every day." - Lao Tzu
Jan 26 '06 #4
Dave Benjamin wrote:
On Thu, 26 Jan 2006, Mr.Rech wrote:
Suppose I'm writing a base class with an __eq__ special methods, using
isinstance() I would have wrote:

class foo(object):
...
def __eq__(self, other):
return isinstance(other, type(self)) and self.an_attribute ==
other.an__attribute Now, avoiding isinstace() I've written the following code:

class foo(object):
...
def __eq__(self, other):
try:
return self.an_attribute == other.an_attribute
except AttributeError:
return False

You were better off with what you had before. Equality in this case is
left completely open-ended, and as a result, there is no way that you
can guarantee that "a == b" is the same as "b == a" if "a" is a "foo"
and "b" is of unknown type. This can lead to bizarre and unpredictable
behavior.


Mind explaining that better? b == a *always* calls b.__eq__(a), if it
exists. What a.__eq__(b) is doesn't matter at that point. So you have
the same problems either way.

The only difference between the two is in the case where b is of an
unrelated class and b.an_attribute exists (1). In this case, the first
always returns False, and the second returns (a.an_attribute ==
b.an_attribute). Which you prefer depends on how strictly you adhere to
duck typing.

(1) To be honest, they also vary when a.an_attribute is undefined. The
second always returns False, and the first raises an AttributeError.
Jan 26 '06 #5
On Thu, 26 Jan 2006, Rocco Moretti wrote:
You were better off with what you had before. Equality in this case is left
completely open-ended, and as a result, there is no way that you can
guarantee that "a == b" is the same as "b == a" if "a" is a "foo" and "b"
is of unknown type. This can lead to bizarre and unpredictable behavior.
Mind explaining that better? b == a *always* calls b.__eq__(a), if it exists.
What a.__eq__(b) is doesn't matter at that point. So you have the same
problems either way.


Right, but we don't know what "b.__eq__" does, since "b" could be
anything, if it exists at all. So, it's quite possible that "a == b",
since "a.__eq__" is defined and only depends on "b" having an
attribute named "an_attribute", but "b == a" is:

a) an error
b) false, even though "a == b" is true

If we control the class of "a" and the class of "b", we can ensure that
the two "__eq__" methods behave identically. The problem is that, in the
supposed interest of "polymorphism" we are relaxing the dependency on
"a.__eq__"'s parameter so that it can be any class with "an_attribute".
This implies that we would like other classes besides those we control to
be able to participate in equality tests with the class of "a". However,
to do this properly, we need to be able to modify *both classes*, or we
will have inconsistent results depending on whether we say "a == b" or
"b == a". It is reasonable to expect that these two expressions produce
the same result, isn't it?
The only difference between the two is in the case where b is of an unrelated
class and b.an_attribute exists (1). In this case, the first always returns
False, and the second returns (a.an_attribute == b.an_attribute). Which you
prefer depends on how strictly you adhere to duck typing.


I don't think duck typing buys you anything valuable here. The usual
flexibility of duck typing is lost because of the symmetric nature of
equality; all participating classes need to be involved to guarantee
correctness. You *could* have "b.__eq__" just call "a.__eq__", but once
again this assumes we have control over the implementation of "b".

--
.:[ dave benjamin -( ramen/sp00 )- http://spoomusic.com/ ]:.

"To attain knowledge, add things every day.
To attain wisdom, remove things every day." - Lao Tzu
Jan 26 '06 #6
On Thu, 26 Jan 2006, Dave Benjamin wrote:
On Thu, 26 Jan 2006, Rocco Moretti wrote:
You were better off with what you had before. Equality in this case is
left completely open-ended, and as a result, there is no way that you can
guarantee that "a == b" is the same as "b == a" if "a" is a "foo" and "b"
is of unknown type. This can lead to bizarre and unpredictable behavior.


Mind explaining that better? b == a *always* calls b.__eq__(a), if it
exists. What a.__eq__(b) is doesn't matter at that point. So you have the
same problems either way.


Right, but we don't know what "b.__eq__" does, since "b" could be anything,
if it exists at all. So, it's quite possible that "a == b", since "a.__eq__"

^^^^^^^^^^^^^^^^^^^

By "it" here, I mean "b.__eq__".
Jan 26 '06 #7
All in all it seems that the implementation that uses isinstance() is
better in this case...

Thanks for your comments,
Andrea.

Jan 26 '06 #8
On Thu, 26 Jan 2006 19:04:13 +0100, Rene Pijlman wrote:
Mr.Rech:
Now, avoiding isinstace() I've written the following code:

class foo(object):
...
def __eq__(self, other):
try:
return self.an_attribute == other.an_attribute
except AttributeError:
return False


This may give unexpected results when you compare a foo with an instance
of a completely different type that happens to have an attribute called
'an_attribute'.

That's a trade-off, isn't it?
On the one hand, you risk false negatives, by refusing to compare against
things you didn't think of. On the other hand, you risk false positives,
by comparing against more generic objects.

I guess that trade-off is one each programmer must decide for herself, in
full understanding of the pros and cons of each method.
--
Steven.

Jan 26 '06 #9
Mr.Rech wrote:
All in all it seems that the implementation that uses isinstance() is
better in this case...


Well what's "better" depends on what you want to happen when you compare
an unrelated class that also defines 'an_attribute'. Unlike in
statically typed languages, certain things are made easier when you
don't check for strict inheritance (like mock and proxy objects). Google
"Duck Typing" for more info.
Jan 26 '06 #10
After reading all your comments and thinking a little to my specific
case, I think it is definetively better to go with the "isinstance()"
implementation. My objects represent mathematical function defined over
a numerical grid, and I hardly think of an unrelated class objects that
could be compared with them in a meaningfull way.

Thanks again to all of you for helping me to better understand another
piece of the Python's world. ;-)

Andrea

Jan 27 '06 #11
Dave Benjamin wrote:
(snip)
You *could* have "b.__eq__" just call "a.__eq__",


Which could lead to strange results (well, actually a good ole infinite
recursion) if b.__eq__ happens to call b.__eq__ too !-)
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jan 27 '06 #12
Mr.Rech wrote:
All in all it seems that the implementation that uses isinstance() is
better in this case...


You could also use something like Zope's Interfaces... But I'm not sure
it's worth the extra complexity.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jan 27 '06 #13
bruno at modulix wrote:
Mr.Rech wrote:
All in all it seems that the implementation that uses isinstance() is
better in this case...


You could also use something like Zope's Interfaces... But I'm not sure
it's worth the extra complexity.


Thanks for your suggestion, but it's not worth the extra complexity at
all.

I've read something about interfaces, but my project will be a
small/middle sized one, and using such a sophisticated tool it would be
like using a cannon to shoot a sparrow (as we are used to say here in
Italy).

Anyway thanks again for your comments.

Andrea

Jan 27 '06 #14
Steven D'Aprano:
Rene Pijlman:
Mr.Rech:
def __eq__(self, other):
try:
return self.an_attribute == other.an_attribute
except AttributeError:
return False


This may give unexpected results when you compare a foo with an instance
of a completely different type that happens to have an attribute called
'an_attribute'.


That's a trade-off, isn't it?

On the one hand, you risk false negatives, by refusing to compare against
things you didn't think of.


Well no, when comparing against things you didn't think of the __eq__
shouldn't return a false False, it should return NotImplemented. After
all, the things you didn't think of are not (yet) implemented.

"A rich comparison method may return NotImplemented if it does not
implement the operation for a given pair of arguments."
http://www.python.org/doc/ref/customization.html

--
René Pijlman

Wat wil jij worden? http://www.carrieretijger.nl
Jan 27 '06 #15
bruno at modulix wrote:
Dave Benjamin wrote:
(snip)

You *could* have "b.__eq__" just call "a.__eq__",

Which could lead to strange results (well, actually a good ole infinite
recursion) if b.__eq__ happens to call b.__eq__ too !-)


I meant:

'if a.__eq__ happens to call b.__eq__ too'

of course...

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jan 27 '06 #16
Mr.Rech wrote:
Hi all,
I've read some thread about isinstance(), why it is considered harmful
and how you can achieve the same results using a coding style that
doesn't break polymorphism etc... Since I'm trying to improve my Python
knowledge, and I'm going to design a class hierarchy from scratch, I'd
like to have some feedback about this from those of you much more
experienced than me in OOP. [snip] Any better way to write this method? Any suggestion?


It's really impossible to tell what's good Python code
based on details like this. isinstance() wouldn't be in
Python if you weren't supposed to use it, but you need to
understand when you should limit your functions to work
with a specific kind of data, and when you should try to
be broader. This is a design decision that will influence
the usability and maintainability of your code. We can't
help you figure out how to make such trade-offs based on
your implementation of __eq__.
Jan 27 '06 #17
Magnus Lycka:
isinstance() wouldn't be in Python if you weren't supposed to use it,


If this argument was correct, 'goto' wouldn't be in Pascal :-)

--
René Pijlman
Jan 27 '06 #18
In <c2********************************@4ax.com>, Rene Pijlman wrote:
Steven D'Aprano:
Rene Pijlman:
Mr.Rech:
def __eq__(self, other):
try:
return self.an_attribute == other.an_attribute
except AttributeError:
return False

This may give unexpected results when you compare a foo with an instance
of a completely different type that happens to have an attribute called
'an_attribute'.


That's a trade-off, isn't it?

On the one hand, you risk false negatives, by refusing to compare against
things you didn't think of.


Well no, when comparing against things you didn't think of the __eq__
shouldn't return a false False, it should return NotImplemented. After
all, the things you didn't think of are not (yet) implemented.


I think Steven thinks that it is possible that you compare to an object of
a different type which has the same attributes as expected by the
`__eq__()` method. If the first test is `isinstance()` for the "correct"
type you rule out those cases and give a false `False`.

Ciao,
Marc 'BlackJack' Rintsch
Jan 27 '06 #19
Marc 'BlackJack' Rintsch:
Rene Pijlman:
Well no, when comparing against things you didn't think of the __eq__
shouldn't return a false False, it should return NotImplemented. After
all, the things you didn't think of are not (yet) implemented.


I think Steven thinks that it is possible that you compare to an object of
a different type which has the same attributes as expected by the
`__eq__()` method. If the first test is `isinstance()` for the "correct"
type you rule out those cases and give a false `False`.


Like I said, it wouldn't return False, it would return NotImplemented.

--
René Pijlman
Jan 27 '06 #20

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

Similar topics

6
by: Michal Vitecek | last post by:
hello, please consider the following situation: under the current directory there's a subdirectory 'package' with two files: __init__.py and module.py ./package: __init__.py module.py
14
by: wolfgang haefelinger | last post by:
Hi, I wonder whether someone could explain me a bit what's going on here: import sys # I'm running Mandrake 1o and Windows XP. print sys.version ## 2.3.3 (#2, Feb 17 2004, 11:45:40)
17
by: Andrew Koenig | last post by:
Suppose I want to define a class hierarchy that represents expressions, for use in a compiler or something similar. We might imagine various kinds of expressions, classified by their top-level...
5
by: Jordan Rastrick | last post by:
Hi everyone, Just a little issue that I've come across in Python where I'd be interested to read the thoughts and opinions of the great thinkers and programmers who frequent this newsgroup. ...
1
by: nitrogenycs | last post by:
Hello, is this call assumed to be True in any case? result = type(SomeClass) is SomeClass I've written a proxy class which shadows a real object. If you call type(proxyobj) it returns the...
12
by: codefire | last post by:
Hi, I'm using the isinstance built-in function. I've found the docs for it, but there are no docs on the supported types. For example isinstance(a, int) works fine but isinstance(s, string)...
4
by: Adam Lanier | last post by:
Relatively new to python development and I have a general question regarding good class design. Say I have a couple of classes: Class Foo: params = __init__( self, param ): ...
7
by: Tlis | last post by:
I am using a software system with an embedded Python interpreter (version 2.3) for scripting. The KcsPoint2D.py module contains a Point2D class with the following method: def...
5
by: Boris Borcic | last post by:
Given the ABC innovation, maybe an infix syntax for isinstance() would be good. Possibilities : - stealing "is" away from object identity. As a motivation, true use cases for testing object...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

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.