3

I am porting some Python 2 code to 3. There is a section that relies on knowing if an object is an instance of a user-defined class, or a built-in. The Python 2 code used:

isinstance(my_object.__class__, Types.ClassType)

python modernize recommends changing "Types.ClassType" to "type". That doesn't work for me because all objects are returning true, we are a "type". From what I understand about classes and Python 3, there is not a difference anymore between built-ins and user-defined classes. I have done almost a full day of research and am getting nowhere. I can't believe I'm the only person in this situation, but maybe I'm not searching the right phrases....

So my question is, is it possible to tell the difference, or do I need to refactor the code so it won't matter?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Bee
  • 195
  • 1
  • 3
  • 12
  • Why, exactly, do you need this distinction? Note, assuming you did `import types` and are using `isinstance(my_object.__class__, types.ClassType)` that isn't checking for user-defined or built-in. Note, if you use a user-defined new-style class, that will return False. – juanpa.arrivillaga May 24 '19 at 19:52
  • What is the code actually doing differently based on this test? If there is some finite set of builit-in types that might be encountered, perhaps you could reverse the test - `not isinstance(my_object, (int, float, str))` for example. – jasonharper May 24 '19 at 19:52

2 Answers2

3

You've likely misunderstood the context. That check is not for detecting a difference between user-defined class or built-in class. This is detecting a difference between old-style class:

class A:
    pass

And new-style class:

class B(object):
    pass

In Python 3+, there are no longer any old-style classes, everything inherits from object whether you asked for it or not. Therefore, you'll want to rewrite or remove any code that special-cased for old-style classes.

Related reading: What is the difference between old style and new style classes in Python?

wim
  • 338,267
  • 99
  • 616
  • 750
3

Check the __module__ attribute of the type. That tells you where the type was defined.

>>> class Test: pass
... 
>>> a = 42
>>> b = Test()
>>> type(a).__module__
'builtins'
>>> type(b).__module__
'__main__'

When classes from other modules are involved it's a bit less trivial, but that was true in Python 2 as well.

Draconis
  • 3,209
  • 1
  • 19
  • 31