1

I have an interface defined as:

class IDefaultedRepo(IRepository):
    """Represents defaulted table in DB"""

    def get_values_by_legalbdr(self, legalbdr: str):    
        raise NotImplementedError

However, this is not explicit enough, as I dont know what fields are returned. I would like to have something like:

class IDefaultedRepo(IRepository):
    """Represents defaulted table in DB"""

    def get_values_by_legalbdr(self, legalbdr: str)->IDefaultedRepo.Result:
       class Result(object):
            def __init__(self, terminal, value, container):
                self.terminal = terminal
                self.value = value
                self.container = container

        raise NotImplementedError

But this throws a NameError, as Result class is not defined yet. Is there any way to specify the return type of a function (so that inner member are accessible by dot . operator), without explicitly create a result class for each function?

EDIT I didnt defined in their own module because I thought there would be too many of them with awkward and lengthy names. Defining an inner class would be nicer since it doesnt force to invent a new class name every time, also, since the return type is specific to a function it makes (?) sens to constraint the scope of the definition only to this function. But yeah, looks like I have to define them in a separate module

dgan
  • 1,349
  • 1
  • 15
  • 28
  • *there is no inner member*. I.E., `Result` would not be a member of `IDefaultedRepo`, i.e., it is neither an instance attribute nor a class-attribute, it is simply a local variable that gets created and discarded every time the *function is called* and *only when the function is called*. – juanpa.arrivillaga Dec 26 '17 at 10:42
  • I don't see how is that relevant?.. – dgan Dec 26 '17 at 10:42
  • 1
    Basically specifying the returned type for function means that you already (universally) know the type and the type is defied already. If you want to create a type inside the function why don't you just create it outside the function? – Mazdak Dec 26 '17 at 10:42
  • The type wouldn't be in the class' namespace anyway, i.e. `IDefaultedRepo.Result` would throw an attribute error. – juanpa.arrivillaga Dec 26 '17 at 10:43
  • 1
    Why do you define the class inside the function. AFAI can tell, that does not solve the issue of "not explicitly creating a result class for each function". Quite the contrary... – user2390182 Dec 26 '17 at 10:43
  • @Kasramvd because there are many functions, and I dont want to pollute the global namespace with class like AgetXResult, AgetYResult,BgetXbyIdResult... – dgan Dec 26 '17 at 10:44
  • Please read https://www.python.org/dev/peps/pep-0484/ to see what's the whole purpose of the type hinting in python. All you're doing seems to be in a contradict with the aforementioned PEP. Also, note that you can simply define your custom types in a separate module and just import them in current module and use them as type hints. – Mazdak Dec 26 '17 at 10:46
  • @dgan why not simply define them in their own name-space? I.E. in their own module? – juanpa.arrivillaga Dec 26 '17 at 10:50
  • @juanpa.arrivillaga I didnt defined in their own module because I thought there would be too many of them with awkward and lengthy names. Defining an inner class would be nicer since it doesnt force to invent a new class name every time, also, since the return type is specific to a function it makes (?) sens to constraint the scope of the definition only to this function. But yeah, looks like I have to define them in a separate module – dgan Dec 26 '17 at 10:55
  • @dgan you don't *have* to, the problem isn't that `Result` isn't defined, it's that `IDefaultedRepo` isn't defined. `IDefaultedRepo.Result` will *never* be defined, because your "inner" class isn't an inner class at all, it is *local* to the function. – juanpa.arrivillaga Dec 26 '17 at 10:57

1 Answers1

0

The problem isn't that Result isn't defined, it's that IDefaultedRepo isn't defined, the solution to this is to use a string. See this closely related question. However, in your case, there will never be an IDefaultedRepo.Result defined, because your "inner" class isn't an inner class at all, it is local to the function. If you actually want an inner class, you need to define the class inside the class-body, not inside the function body.

Something like this:

In [1]: class IRepository: pass

In [2]: class IDefaultedRepo(IRepository):
   ...:     """Represents defaulted table in DB"""
   ...:
   ...:     class Result:
   ...:         def __init__(self, terminal, value, container):
   ...:             self.terminal = terminal
   ...:             self.value = value
   ...:             self.container = container
   ...:
   ...:     def get_values_by_legalbdr(self, legalbdr: str)->'IDefaultedRepo.Result':
   ...:        raise NotImplementedError
   ...:

It wouldn't be my first inclination, though...

But the following checks out with mypy:

class IRepository: pass

class IDefaultedRepo(IRepository):
    """Represents defaulted table in DB"""

    class Result:
        def __init__(self, terminal, value, container):
            self.terminal = terminal
            self.value = value
            self.container = container

    def get_values_by_legalbdr(self, legalbdr: str)->'IDefaultedRepo.Result':
       raise NotImplemented

class MyIDefaultRepo(IDefaultedRepo):
    def get_values_by_legalbdr(self, legalbdr: str)->'IDefaultedRepo.Result':
        class MyResult(IDefaultedRepo.Result):
            pass
        return MyResult('foo','bar','baz')
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172