An object is and isn't an instance of a class at the same time

D

danielk

I was debugging some code using isinstance() to make sure the correct object was been passed to the method and came across something that is really ticking me off.

I have a class called 'Jitem' in its own file called 'jitem.py'. It's part of a package called 'jukebox'. I also have '__all__' that includes 'jitem' so that I can do:

from jukebox import *

There is another class that has a method that does this (simplified for this example):

def execute(self, command):

I stuck this debug code in the method:

if not isinstance(command, jitem.Jitem):
print(command.__class__)
raise TypeError("Command must be an instance of Jitem.")

When this method gets run in a test script, it returns this:

D:\home\python>python jtest.py
<class 'jukebox.jitem.Jitem'>
Traceback (most recent call last):
File "jtest.py", line 4, in <module>
executeResults = jc.execute(cmnd)
File "D:\home\python\jukebox\jconnection.py", line 225, in execute
raise TypeError("Command must be an instance of Jitem.")
TypeError: Command must be an instance of Jitem.

How can it both get past isinstance() and still say it is the proper class?

Dan Klein
 
C

Chris Angelico

D:\home\python>python jtest.py
<class 'jukebox.jitem.Jitem'>
Traceback (most recent call last):
File "jtest.py", line 4, in <module>
executeResults = jc.execute(cmnd)
File "D:\home\python\jukebox\jconnection.py", line 225, in execute
raise TypeError("Command must be an instance of Jitem.")
TypeError: Command must be an instance of Jitem.

How can it both get past isinstance() and still say it is the proper class?

You're invoking it as __main__ and then also importing it. This gives
you two instances of your module, with two separate classes that have
the same name and (presumably) the same definition.

If you use a separate driver script, you won't see this problem.
Alternatively, simply stop checking isinstance and trust that, if
something incompatible gets passed in, it'll throw an exception
somewhere. That's usually enough.

ChrisA
 
D

Dave Angel

You're invoking it as __main__ and then also importing it. This gives
you two instances of your module, with two separate classes that have
the same name and (presumably) the same definition.

If you use a separate driver script, you won't see this problem.
Alternatively, simply stop checking isinstance and trust that, if
something incompatible gets passed in, it'll throw an exception
somewhere. That's usually enough.

Just to elaborate on ChrisA's comments. You have a script which imports
a module, which in turn imports the script. That's called recursive
imports, and is a "BAD THING."

It can cause various problems, but in the particular case of importing
the top-level script, it can cause a very confusing one as you see
here. There are two copies of any classes defined in the script, and
the system treats them as independent classes which only happen to have
the same name. isInstance() is one place you might notice this, but
class static variables and even "global" variables in that module are
also candidates. The real problem is that sometimes people treat the
symptom and never fix the underlying problem, the recursive import.

Whenever you have "a imports b, which imports a," or you have "a
imports b, which imports c, which imports a," you run the risk of
something getting initialized out of order, or worse getting initialized
twice. You need to fix that, usually by factoring out some part which
is recursive, and moving it to an independent module which gets imported
by both the others.

You can also get into this type of confusion by importing a module by
two different names, for example if you import it from a directory in
one place, and from a package in another.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top