Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper use of `isinstance(obj, class)`

As I write it, it seems almost surreal to me that I'm actually experiencing this problem.

I have a list of objects. Each of these objects are of instances of an Individual class that I wrote.

Thus, conventional wisdom says that isinstance(myObj, Individual) should return True. However, this was not the case. So I thought that there was a bug in my programming, and printed type(myObj), which to my surprise printed instance and myObj.__class__ gave me Individual!

>>> type(pop[0])
<type 'instance'>
>>> isinstance(pop[0], Individual) # with all the proper imports
False
>>> pop[0].__class__
Genetic.individual.Individual

I'm stumped! What gives?

EDIT: My Individual class

class Individual:
    ID = count()
    def __init__(self, chromosomes):
        self.chromosomes = chromosomes[:]    # managed as a list as order is used to identify chromosomal functions (i.e. chromosome i encodes functionality f)
        self.id = self.ID.next()

    # other methods
like image 1000
inspectorG4dget Avatar asked Oct 23 '12 20:10

inspectorG4dget


2 Answers

This error indicates that the Individual class somehow got created twice. You created pop[0] with one version of Instance, and are checking for instance with the other one. Although they are pretty much identical, Python doesn't know that, and isinstance fails. To verify this, check whether pop[0].__class__ is Individual evaluates to false.

Normally classes don't get created twice (unless you use reload) because modules are imported only once, and all class objects effectively remain singletons. However, using packages and relative imports can leave a trap that leads to a module being imported twice. This happens when a script (started with python bla, as opposed to being imported from another module with import bla) contains a relative import. When running the script, python doesn't know that its imports refer to the Genetic package, so it processes its imports as absolute, creating a top-level individual module with its own individual.Individual class. Another other module correctly imports the Genetic package which ends up importing Genetic.individual, which results in the creation of the doppelganger, Genetic.individual.Individual.

To fix the problem, make sure that your script only uses absolute imports, such as import Genetic.individual even if a relative import like import individual appears to work just fine. And if you want to save on typing, use import Genetic.individual as individual. Also note that despite your use of old-style classes, isinstance should still work, since it predates new-style classes. Having said that, it would be highly advisable to switch to new-style classes.

like image 196
user4815162342 Avatar answered Sep 22 '22 04:09

user4815162342


You need to use new-style classes that inherit from

class ClassName(object):
    pass

From your example, you are using old-style classes that inherit from

class Classname:
    pass

EDIT: As @user4815162342 said,

>>> type(pop[0])
<type 'instance'>

is caused by using an old-style class, but this is not the cause of your issues with isinstance. You should instead make sure you don't create the class in more than one place, or if you do, use distinct names. Importing it more than once should not be an issue.

like image 41
bossylobster Avatar answered Sep 20 '22 04:09

bossylobster