简体   繁体   中英

Python: How do you specify the parameter type of a Class function to the current class?

I'm writing a set of custom classes with inheritance using Python. Here is the code, simplified:

class Parent(object):
    __slots__ = ['a','b']

    def __init__(self, a:int, b:int):
        self.a = a
        self.b = b
    
    def myfunc(self,s)->int:
        return self.a + s.a

class Child(Parent):
    __slots__ = ['c']

    def __init__(self, a:int, b:int, c:int):
        super().__init__(a,b)
        self.c = c

    def myfunc(self,s)->int:
        return self.a + s.a + s.c

def main():
    dad = Parent(1,2)
    son = Child(4,8,16)

    print(dad.myfunc(son))
    print(son.myfunc(son))
    print(son.myfunc(dad))

if __name__ == "__main__":
    main()

Upon running the function, I get this output (which I understand):

5
24
Error: Parent has no attribute 'c'

The myfunc() definition in Child requires that both self AND s are instances of Child.

My ideal functionality for this code is that I want to implement method overloading. When son.myfunc(dad) is called, I want it to check the type of dad. If dad is also a Child , it should use Child 's definition of myfunc() . Otherwise, if dad isn't a Child , son should fall back to using the definition of myfunc() in Parent . So, for the above code, I'd want:

5
24
5

I would've thought that I could implement this functionality as follows, specifying the parameter types of myfunc() :

class Parent(object):
    __slots__ = ['a','b']

    def __init__(self, a:int, b:int):
        self.a = a
        self.b = b
    
    def myfunc(self, s:Parent)->int:
        return self.a + s.a

class Child(Parent):
    __slots__ = ['c']

    def __init__(self, a:int, b:int, c:int):
        super().__init__(a,b)
        self.c = c

    def myfunc(self,s:Child)->int:
        return self.a + s.a + s.c

def main():
    dad = Parent(1,2)
    son = Child(4,8,16)

    print(dad.myfunc(son))
    print(son.myfunc(son))
    print(son.myfunc(dad))

if __name__ == "__main__":
    main()

However, this doesn't work. Python and my IDE tell me that "Parent is not defined" by the time I use it to specify the input type of Parent's myfunc() , and the same for Child . I think I get what it's saying (' Parent ' won't mean anything until the compiler finishes reading Parent, so it can't be specified as the parameter type), but I don't know how to work around this.

How can I implement my intended functionality? Is there some keyword like 'this' or 'self' that can be used to refer to the current class's type for these specifications? Even if method overloading doesn't work in this way- is there a way for a single class ( Parent ) to specify itself as the parameter type of one of its functions?

Edit: I'm aware that Python parameter types are annotations for readability and error-checking, and they don't actually cause errors/failures if called with a different type. The second code segment was created to help communicate what I want to have occur. I'm aware I might have to add a check like isinstance() at the start of myfunc, but (a) I would like to avoid it if there is an alternative (b) if I did discover in the body of Child's myfunc() that I wanted to call the Parent's instead, I'm not certain of how I'd do that.

You have two separate issues:

  1. In order to type-hint a method that returns its own class ( forward reference ) you should use a string:

     def myfunc(self, s: "Parent") -> int:
  2. You can use isinstance to check for type, ie

    def myfunc(self, s: "Child") -> int: return (self.a + sa + sc) if isinstance(s, Child) else (self.a + sa)

As a side note the type of s in your Child.myfunc should probably be Parent .

Update: Per your comment, the following should be possible:

class Parent(object):
    # ...

    def _myfunc(self, s: "Parent") -> int:
        return self.a + s.a

    def myfunc(self, s: "Parent") -> int:
        return type(s)._myfunc(self, s)

class Child(Parent):
    # ...

    def _myfunc(self, s: "Parent") -> int:
        return self.a + s.a + s.c

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM