0

I want to do something like

class my_class:
    def __add__(self, other: "my_class") -> "my_class":
        if isinstance(other, some_other_class):
            return other + self
        elif isinstance(other, my_class):
            return <special_adding_technique>
        else:
            raise NotImplementedError()

But I can't, as I can't reference my_class inside of itself. I can do some duck typing, with try except, or check has_attr, but this is far less clean than simply checking isinstance. What can I do which is simple and doesn't look hacky?

1 Answer 1

1

You can reference my_class inside itself just fine. You can't refer to my_class while it's being defined (outside any method, at the top-level of the class definition scope, or in the parameter definitions of a function), but you can refer to it inside a method that won't be called until you've finished defining my_class. The only issue you have here is the somewhat ugly string-based annotations to work around the self-reference limitation, which can be fixed with a __future__ import.

from __future__ import annotations  # Supported as of 3.7, on by default beginning in 3.11

class my_class:
    def __add__(self, other: my_class) -> my_class:
        if isinstance(other, some_other_class):
            return other + self
        elif isinstance(other, my_class):
            return <special_adding_technique>
        return NotImplemented   # When you can't work with the other type, you're supposed
                                # to return the NotImplemented singleton, not raise
                                # NotImplementedError, where the latter is for completely
                                # unimplemented functionality, usually in an ABC

As a side-note, Python classes are the exception to the normal naming rule of lowercase or lowercase_with_underscores; classes use CapWords, so this class should be named MyClass to comply with PEP8.

Sign up to request clarification or add additional context in comments.

2 Comments

you're right.. my stupid linter refused to acknowledge that this is possible, initially giving me a red underline. it believes in me now, thanks
@JerryHalisberry: Cool. A bonus side-note: Your if isinstance(other, some_other_class): return other + self is likely wrong too. If other defines __radd__ correctly (and it should), then that case can and should be handled by returning NotImplemented from my_class.__add__, just like you do for all other classes you don't know how to add yourself to. When you return NotImplemented, Python asks the right hand side if it knows how to perform the reflected operation (in this case, __radd__), and only if both sides return NotImplemented does it fail with a TypeError.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.