Is using Python `isinstance` ever correct?

I have a 2D array of different blocks, all inherit from Block. I want to check if the block I clicked on was a block of type Dirt, for example:

clickedblock = getClickedBlock() if isinstance(clickedblock, Dirt): place a block else: don't place a block 

I heard that isinstance bad and should be avoided as it creates forks in the code. What times could isinstance be used?

Another more cumbersome solution for my problem would be to have a Block field called 'id' and then check if it is equal to constants, which means Dirt. But it sounds pretty bad and more error prone than simple isinstance .

+6
source share
4 answers

Your example seems to be a legitimate use isinstance() for isinstance() .

It’s not that isinstance() bad, often polymorphism can be used for the same purpose (which leads to the creation of cleaner code in the place where the class is used).

But sometimes isinstance() is what you need. For example, the pythonic way of determining if a variable is a string or not isinstance(var, basestring) .

+6
source

If you do not want to use it, you have other options. Traditional duck printing solution:

 try: clickedblock_place = clickedblock.place except AttributeError: # don't place block else: clickedblock_place() 

Or you can use hasattr:

 if hasattr(clickedblock, 'place'): clickedblock.place() 

I almost never use isinstance, except for checking (or is it down?) The inheritance hierarchy, say, for example, if you need to know if the name points to str or unicode:

 if isinstance(str1, basestring): blah, blah, blah 

Good luck, Mike

+1
source

I think I would modify it to be more like:

 PLACEABLE_TYPES = [ Dirt ] if isinstance(clickedblock, PLACEABLE_TYPES): place the block else: don't place the block 

but the idea is in the comments:

 if clickedblock.is_placeable(that_place): place the block else: don't place the block 

also has advantages.

0
source

I learned hard against using it. The problem is that the result depends on how the class definitions were imported:

  • in the place where the object was created
  • in the place where isinstance check

If one import was relative and the other absolute, the check will fail. In essence, this will be similar to checking the equality of SomeClass and somepackage.SomeClass . It doesn’t even matter that they come from a single file and so on. In addition, there will be a similar result if somehow the root directory and somepackage directory are somepackage - then import in absolute style can indicate the path from any of the “source roots”, so as a result somepackage will somepackage two different imports in absolute style. in case of unsuccessful instance checks.

One can argue about how good practices will prevent this anyway, but good practices also basically come down to not taking risks. In this spirit, I prefer to put some kind of abstract method in a common class of ancestors, so that later I can rely on how things quack, and not how the interpreter considers them.

In Java, each class is converted to a fully qualified class name. They are unique within the program, and instance tests are very simple. In Python, they can be slippery.

0
source

All Articles