2

There is a Class from a third party lib I am using.

def funcA(base):
    class ClassA(base):
        def __init__(self, obj):
        ....

I have an instance of ClassA a

type(a)

# prints <class 'path.to.module.funcA.<locals>.ClassA'>

How can I check if a variable is an instance of ClassA? I am not sure how to reference ClassA since it is under a function....

import module
isinstance(a, module.funcA.ClassA?) <--- how to reference ClassA?
OLIVER.KOO
  • 5,654
  • 3
  • 30
  • 62
  • Why do you need to do such a test? Define interfaces, adopt duck typing. BTW, if that class is local to the function, either it's bad OO design or you're trying to tweak things – Pynchia Aug 21 '20 at 03:45
  • 1
    No such check is possible, at least not in any usual way. There's no way to reference the class directly, and in fact a brand new class object is created every time the function is called. All of the classes have the same name, and behave identically - but an instance of one class version fails the `isinstance` check with any other version. The best you could do would be something like `type(a).__name__ == "ClassA"`. – jasonharper Aug 21 '20 at 03:50
  • You could return an ClassA object, but that’s the best I could get from what I found. Somehow related: https://stackoverflow.com/questions/2024566/how-to-access-outer-class-from-an-inner-class – hedy Aug 21 '20 at 03:56
  • Python *doesn't have class declarations* (or any declarations, really). A class definition statement is essentially syntactic sugar for a call to the `type` constructor, assigning the resulting class object to the `ClassA` local variable. Like any local variable, it isn't accessible outside the function – juanpa.arrivillaga Aug 21 '20 at 10:16
  • Now, yuo *can* recover the class if you have an instance of it, `ClassA = type(a)` and now you can reference `ClassA` in that scope – juanpa.arrivillaga Aug 21 '20 at 10:17

1 Answers1

0

If you are not able to change funcA itself because it's not in your own code, then a neat way to test for instances is to give it a superclass and test for the superclass. Replace funcA with a wrapped version, which calls the original funcA with a class that extends both base and your own ClassABase:

import functools

class ClassABase:
    pass

def funcAwrapper(f):
    @functools.wraps(f)
    def wrapper(base):
        class WrappedBase(base, ClassABase):
            pass
        return f(WrappedBase)
    return wrapper

funcA = funcAwrapper(funcA)

Now all of the instances of ClassA created by funcA will also be instances of your own ClassABase, so you can test isinstance(obj, ClassABase).

kaya3
  • 47,440
  • 4
  • 68
  • 97