The following code does not work as expected. Apparently, I cannot use the classes' own type inside class definition:
class Foo: def __init__(self, key :str) -> None: self.key = key def __eq__(self, other :Foo) -> bool: return self.key == other.key print('should be true: ', Foo('abc') == Foo('abc')) print('should be false: ', Foo('abc') == Foo('def'))
The result of running it is:
Traceback (most recent call last): File "class_own_type.py", line 1, in <module> class Foo: File "class_own_type.py", line 5, in Foo def __eq__(self, other :Foo) -> bool: NameError: name 'Foo' is not defined
Also, checking the code with mypy
returns:
class_own_type.py:5: error: Argument 1 of "__eq__" incompatible with supertype "object"
How can I correct this code to be valid, both for Python and for mypy
?
type is a metaclass, of which classes are instances. Just as an ordinary object is an instance of a class, any new-style class in Python, and thus any class in Python 3, is an instance of the type metaclass. In the above case: x is an instance of class Foo . Foo is an instance of the type metaclass.
First, extract the class body as string. Second, create a class dictionary for the class namespace. Third, execute the class body to fill up the class dictionary. Finally, create a new instance of type using the above type() constructor.
Python Code can be dynamically imported and classes can be dynamically created at run-time. Classes can be dynamically created using the type() function in Python. The type() function is used to return the type of the object. The above syntax returns the type of object.
class types. SimpleNamespace. A simple object subclass that provides attribute access to its namespace, as well as a meaningful repr. Unlike object , with SimpleNamespace you can add and remove attributes.
The name Foo
isn't bound yet, because the class itself has not yet been defined at the time that you try to use the name (remember: function arguments are evaluated at function definition time, not at function call time).
From Python 3.7+ you can postpone evaluation of annotations by adding this import at the top of the module:
from __future__ import annotations
In Python 3.10 postponed evaluation will become the default behavior. For Python < 3.7, you can use string literals to delay evaluation of the type:
class Foo: def __init__(self, key :str) -> None: self.key = key def __eq__(self, other: 'Foo') -> bool: return self.key == other.key print('should be true: ', Foo('abc') == Foo('abc')) print('should be false: ', Foo('abc') == Foo('def'))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With