| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- .. _native-classes:
- Native classes
- ==============
- Classes in compiled modules are *native classes* by default (some
- exceptions are discussed below). Native classes are compiled to C
- extension classes, which have some important differences from normal
- Python classes. Native classes are similar in many ways to built-in
- types, such as ``int``, ``str``, and ``list``.
- Immutable namespaces
- --------------------
- The type object namespace of native classes is mostly immutable (but
- class variables can be assigned to)::
- class Cls:
- def method1(self) -> None:
- print("method1")
- def method2(self) -> None:
- print("method2")
- Cls.method1 = Cls.method2 # Error
- Cls.new_method = Cls.method2 # Error
- Only attributes defined within a class definition (or in a base class)
- can be assigned to (similar to using ``__slots__``)::
- class Cls:
- x: int
- def __init__(self, y: int) -> None:
- self.x = 0
- self.y = y
- def method(self) -> None:
- self.z = "x"
- o = Cls(0)
- print(o.x, o.y) # OK
- o.z = "y" # OK
- o.extra = 3 # Error: no attribute "extra"
- .. _inheritance:
- Inheritance
- -----------
- Only single inheritance is supported (except for :ref:`traits
- <trait-types>`). Most non-native classes can't be used as base
- classes.
- These non-native classes can be used as base classes of native
- classes:
- * ``object``
- * ``dict`` (and ``Dict[k, v]``)
- * ``BaseException``
- * ``Exception``
- * ``ValueError``
- * ``IndexError``
- * ``LookupError``
- * ``UserWarning``
- * ``typing.NamedTuple``
- * ``enum.Enum``
- By default, a non-native class can't inherit a native class, and you
- can't inherit from a native class outside the compilation unit that
- defines the class. You can enable these through
- ``mypy_extensions.mypyc_attr``::
- from mypy_extensions import mypyc_attr
- @mypyc_attr(allow_interpreted_subclasses=True)
- class Cls:
- ...
- Allowing interpreted subclasses has only minor impact on performance
- of instances of the native class. Accessing methods and attributes of
- a *non-native* subclass (or a subclass defined in another compilation
- unit) will be slower, since it needs to use the normal Python
- attribute access mechanism.
- You need to install ``mypy-extensions`` to use ``@mypyc_attr``:
- .. code-block:: text
- pip install --upgrade mypy-extensions
- Class variables
- ---------------
- Class variables must be explicitly declared using ``attr: ClassVar``
- or ``attr: ClassVar[<type>]``. You can't assign to a class variable
- through an instance. Example::
- from typing import ClassVar
- class Cls:
- cv: ClassVar = 0
- Cls.cv = 2 # OK
- o = Cls()
- print(o.cv) # OK (2)
- o.cv = 3 # Error!
- .. tip::
- Constant class variables can be declared using ``typing.Final`` or
- ``typing.Final[<type>]``.
- Generic native classes
- ----------------------
- Native classes can be generic. Type variables are *erased* at runtime,
- and instances don't keep track of type variable values.
- Compiled code thus can't check the values of type variables when
- performing runtime type checks. These checks are delayed to when
- reading a value with a type variable type::
- from typing import TypeVar, Generic, cast
- T = TypeVar('T')
- class Box(Generic[T]):
- def __init__(self, item: T) -> None:
- self.item = item
- x = Box(1) # Box[int]
- y = cast(Box[str], x) # OK (type variable value not checked)
- y.item # Runtime error: item is "int", but "str" expected
- Metaclasses
- -----------
- Most metaclasses aren't supported with native classes, since their
- behavior is too dynamic. You can use these metaclasses, however:
- * ``abc.ABCMeta``
- * ``typing.GenericMeta`` (used by ``typing.Generic``)
- .. note::
- If a class definition uses an unsupported metaclass, *mypyc
- compiles the class into a regular Python class*.
- Class decorators
- ----------------
- Similar to metaclasses, most class decorators aren't supported with
- native classes, as they are usually too dynamic. These class
- decorators can be used with native classes, however:
- * ``mypy_extensions.trait`` (for defining :ref:`trait types <trait-types>`)
- * ``mypy_extensions.mypyc_attr`` (see :ref:`above <inheritance>`)
- * ``dataclasses.dataclass``
- * ``@attr.s(auto_attribs=True)``
- Dataclasses and attrs classes have partial native support, and they aren't as
- efficient as pure native classes.
- .. note::
- If a class definition uses an unsupported class decorator, *mypyc
- compiles the class into a regular Python class*.
- Deleting attributes
- -------------------
- By default, attributes defined in native classes can't be deleted. You
- can explicitly allow certain attributes to be deleted by using
- ``__deletable__``::
- class Cls:
- x: int = 0
- y: int = 0
- other: int = 0
- __deletable__ = ['x', 'y'] # 'x' and 'y' can be deleted
- o = Cls()
- del o.x # OK
- del o.y # OK
- del o.other # Error
- You must initialize the ``__deletable__`` attribute in the class body,
- using a list or a tuple expression with only string literal items that
- refer to attributes. These are not valid::
- a = ['x', 'y']
- class Cls:
- x: int
- y: int
- __deletable__ = a # Error: cannot use variable 'a'
- __deletable__ = ('a',) # Error: not in a class body
- Other properties
- ----------------
- Instances of native classes don't usually have a ``__dict__`` attribute.
|