0

I want to be able to pass an instance of Foo to another instance of Foo.

My below code doesn't work for two reasons:

  1. I need to use Foo in MyTypes before Foo is known. I get a NameError that Foo is not known

  2. In my check isinstance(values,Foo) my instance of Foo is not recognized and I get my TypeError "Type not supported".

Can someone explain me how I can fix this?

Thanks!

MyTypes = (list,np.ndarray, Foo)
class Foo():

    def __init__(self,values:MyTypes) -> None:
        self.values = self._unpack_values(values)

    def _unpack_values(self,values):
        if not isinstance(values,MyTypes): 
            raise TypeError("Type not supported")
        else:
            if isinstance(values, list): 
                return "list"
            elif isinstance(values, Foo):
                return "Foo"
            elif isinstance(values, np.ndarray):
                return "np.ndarray"
            else:
                return ValueError("Something went wrong")

f = Foo(values=Foo(values=[1,2,3]))
FredMaster
  • 1,211
  • 1
  • 15
  • 35
  • 1
    Does this answer your question? [How do I specify that the return type of a method is the same as the class itself?](https://stackoverflow.com/questions/33533148/how-do-i-specify-that-the-return-type-of-a-method-is-the-same-as-the-class-itsel) – mkrieger1 Apr 24 '20 at 18:09
  • Thanks. Not using MyTypes and instead solved the problem. This explains why I never encountered this problem, because I just started playing around with annotationts. Thanks! – FredMaster Apr 24 '20 at 18:14
  • using `from __future__ import annotations` as recommended in the link does not solve the issue, however. – FredMaster Apr 24 '20 at 18:16

2 Answers2

1

MyTypes only serve as the annotation to your __init__, since you can't have Foo reference before it's created, I'd recommend you forget about the annotation and just remove MyTypes altogether.

# MyTypes = (list,np.ndarray, Foo)
# I would remove this

class Foo:

    def __init__(self,values) -> None:
        self.values = self._unpack_values(values)

    def _unpack_values(self,values):
        # only start referencing Foo from here as a validation
        if not isinstance(values, (list, ndarray, Foo)): 
            raise TypeError("Type not supported")
        else:
            if isinstance(values, list): 
                return "list"
            elif isinstance(values, Foo):
                return "Foo"
            elif isinstance(values, np.ndarray):
                return "np.ndarray"
            else:
                return ValueError("Something went wrong")

f = Foo(values=Foo(values=[1,2,3]))

The challenge is that you can't reference Foo before class Foo or within its body until you're in the methods. I don't see there's much benefit to have MyTypes so this would be the simplest fix.

r.ook
  • 13,466
  • 2
  • 22
  • 39
0

One ugly route you can go down is just make a shell class then add the methods from functions after the fact:

import numpy as np

class Foo():
    pass

MyTypes = (list,np.ndarray, Foo)

def __init__(self,values:MyTypes) -> None:
    self.values = self._unpack_values(values)

def _unpack_values(self,values):
    if not isinstance(values,MyTypes): 
        raise TypeError("Type not supported")
    else:
        if isinstance(values, list): 
            return "list"
        elif isinstance(values, Foo):
            return "Foo"
        elif isinstance(values, np.ndarray):
            return "np.ndarray"
        else:
            return ValueError("Something went wrong")

Foo.__init__ = __init__
Foo._unpack_values = _unpack_values

f = Foo(values=Foo(values=[1,2,3]))

python tutor link to code

Phillyclause89
  • 674
  • 4
  • 12