Search code examples
python-3.xooptyping

Python: error when importing Class defined via function type()


Trying to understand some source code, I run into an issue I cannot figure out. I created a minimum example as follows. I have a main file and a module, named main_file.py and Problem.py.

The main file contains a Class definition, as well as a function that returns another class via the type(name, bases, dict) function,

import numpy


class BoundMetaClass:
    def __init__(self, value):
            
        if isinstance(value, numpy.ndarray):
            _value = value   
    @property
    def g(self):
        return self.value 


def bound(value) -> BoundMetaClass:
    bctype = int
    formcls = type("Bound", (int,), {})
    return formcls(value)

# bound(3)
# the error persists even if a Bound class object is initiated

import Problem

the module I am trying to import looks life, fleshed out to the bare bones just to make the error visible

from typing import List

class Problem:
   

    def __init__(self, bcs: List[Bound]):  
        self.attr1 = True
        self.attr2 = False

now I save them in the same folder, run python main_file.py an get the error

NameError: name 'Bound' is not defined

Should not the Bound Class have been defined by type() in main_file.py?

The same error is retrieved if I use

def __init__(self, bcs: List[BoundMetaClass]):  

but surely BoundMetaClass have been defined.

Sorry if it is trivial, it is my first attempt to understand type() or such stuff, thanks


Solution

  • The type function does create a type, but as the type is declared within a function body, it is not available in the module's namespace. This means you cannot import it into your problem.py module.

    If you really wanted to use the type function in this way, you'd need to invoke the function at the module level:

    class BoundMetaClass:
        def __init__(self, value):
                
            if isinstance(value, numpy.ndarray):
                _value = value   
        @property
        def g(self):
            return self.value 
    
    Bound = type("Bound", (int,), {})
    
    # In problem.py
    
    from typing import List
    from main_file import Bound
    ...