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

Discussion in 'Python' started by danielk, Dec 9, 2012.

  1. danielk

    danielk Guest

    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
    danielk, Dec 9, 2012
    #1
    1. Advertising

  2. On Mon, Dec 10, 2012 at 10:34 AM, danielk <> wrote:
    > 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
    Chris Angelico, Dec 10, 2012
    #2
    1. Advertising

  3. danielk

    Dave Angel Guest

    On 12/09/2012 07:31 PM, Chris Angelico wrote:
    > On Mon, Dec 10, 2012 at 10:34 AM, danielk <> wrote:
    >> 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.
    >
    >


    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.

    --

    DaveA
    Dave Angel, Dec 10, 2012
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sridhar R
    Replies:
    14
    Views:
    1,382
    =?iso-8859-1?Q?Fran=E7ois?= Pinard
    Feb 10, 2004
  2. Daniel Lipovetsky
    Replies:
    2
    Views:
    342
    Jordan Greenberg
    Mar 12, 2007
  3. Gre7g Luterman

    What is an instance and what isn't?

    Gre7g Luterman, May 24, 2007, in forum: Python
    Replies:
    4
    Views:
    304
    Gabriel Genellina
    May 24, 2007
  4. Martin P. Hellwig
    Replies:
    1
    Views:
    367
    Martin P. Hellwig
    Mar 26, 2010
  5. Christoph Groth
    Replies:
    8
    Views:
    224
    Carl Banks
    Jun 21, 2010
Loading...

Share This Page