seems like a bug in isinstance()

Chris Rebert clp2 at rebertia.com
Fri May 6 05:57:39 EDT 2011


On Fri, May 6, 2011 at 2:24 AM, dmitrey <dmitrey15 at gmail.com> wrote:
> hi all,
>
> suppose I've created a class Point in file .../openopt/kernel/Point.py
>
> Consider the code in file .../somewhere/file1.py
> from openopt.kernel.Point import Point
> p = Point()
>
> now let's pass p into a func from .../openopt/kernel/file2.py and
> check
> from Point import Point
> isinstance(p, Point)
>
> So, it returns False!
>
> p is <Point.Point instance at 0x30801b8>, while Point is <class
> openopt.kernel.Point.Point at 0x2048e20>
>
> [Subject: seems like a bug in isinstance()]

This is due to a peculiarity of how (C)Python's import machinery
works; isinstance() is working just fine.
(And if you ever think you've found a bug in Python's built-ins, odds
are you haven't. Python has been around too long, someone ought to
have encountered it earlier, statistically speaking.)

Note how the class is referred to as both Point.Point and
openopt.kernel.Point.Point. This is because you did `from Point import
...` in file2.py, whereas in file1.py you did `from
openopt.kernel.Point import ...`. These 2 different ways of referring
to the same module are sufficient to "trick"/"outsmart" (C)Python and
cause it to import the same module twice as 2 separate instances (i.e.
it gets re-executed). Why the import machinery isn't smarter in this
situation, I don't recall.

The output of this should be illuminating:
print(Point, type(p), type(p) is Point, id(Point), id(type(p)))
As this demonstrates, you're dealing with 2 separate definitions of
the same Point class.

Solution: Avoid the implicitly-relative `from Point import ...` style
of import; always use the absolute `from openopt.kernel.Point import
...` style instead. Subsequent imports will thus reference the
already-previously-imported instance of a module rather than importing
a copy of it from scratch again.

Cheers,
Chris
--
http://rebertia.com



More information about the Python-list mailing list