pythonpython-3.xpython-decoratorspython-packagingmodular-design

Object instance type checking from another file


I have modularized my python code into three files. File1.py has a class definition with its methods and attributes defined inside of the class. File2.py serves as a layer between the input that comes to the program and then calls the methods and operates on those inputs, basically acting as an interface. While File3.py I made it for sanity check for inputs. I am decorating the relevant methods of the class with some sanity-check decorators defined in File3.py. One such decorator has python's isinstance(input_received, class_name). Now, since checking is happening in File3, class is defined in File1, the decorator is taking only class method as an input, where input(class) method has (self, input_received), my isinstance(input_received, class_name) statement is throwing an error that "'class_name' is unknown", which means class_name definition is not in File3's scope. I've imported File3 in File1, and File1 in File2. Also, cyclic importing is not an option. It'll be a dumb thing to do. I mean, importing File3 in File1 in addition to all the existing imports.

Please help!

File1 (arith.py)

import decors # importing the decorator for input sanity check

class Coords(object):
    def __init__(self, x, y):
        self.abscissa = x
        self.ordinate = y

    def __add__(self, other):
        """ Normal left operand addition """
        return Coords(self.abscissa + other.abscissa, self.ordinate + other.ordinate)

    def __neg__(self):
        """ Negation """
        return Coords(-self.abscissa, -self.ordinate)

    @decors.neg_san_check # decorating __sub__ method
    def __sub__(self, other):
        """ Normal left operand subtraction """
        return self + other.__neg__()

File3 (decors.py)

from functools import wraps

def neg_san_check(func):
    @wraps(func)
    def wrapper(obj_ref, other_obj):
          if isinstance(other_obj, (Coords, int, float)):
                func(obj_ref, other_obj)
    return wrapper

File2 (base.py)

from arith import Coords

c1 = Coords(3,6)
c2 = Coords(7,8)

diff = c1-c2
print(diff.abscissa)
print(diff.ordinate)

Here's an error:

Traceback (most recent call last):
  File "base.py", line 6, in <module>
    diff = c1-c2
  File "/home/somepath/codedir/decors.py", line 6, in wrapper
    if isinstance(other_obj, (Coords, int, float)):
NameError: name 'Coords' is not defined

Note: All 3 files lies in codedir directory


Solution

  • After struggling through many websites, here I came up the solution for File3 (decors.py)

    from functools import wraps
    
    def neg_san_check(func):
        @wraps(func)
        def wrapper(obj_ref, other_obj):
              if isinstance(other_obj, (obj_ref.__class__, int, float)):
                    func(obj_ref, other_obj)
    

    I would also like to add one more scenario: Suppose if we have assure that the passed instance(other_obj) is of type some other class (which is different from 'obj_ref.class', then we can pass that OTHER CLASS's class variable (whose sole purpose is to use for type checking out of its own class) to the function which is decorated in the current class.