Skip to content

Commit bc2b303

Browse files
authored
[mypyc] Document behavior of allow_interpreted_subclasses (#22064)
Document possible surprises arising when using `@mypyc_attr(allow_interpreted_subclasses=True)`: - Setting value of an inherited attribute at class level does not update the native attribute - Overriding a `@final` method has no effect in native code
1 parent 1a45221 commit bc2b303

1 file changed

Lines changed: 54 additions & 0 deletions

File tree

‎mypyc/doc/native_classes.rst‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,60 @@ a *non-native* subclass (or a subclass defined in another compilation
8383
unit) will be slower, since it needs to use the normal Python
8484
attribute access mechanism.
8585

86+
Note that setting the value of an attribute inherited from a native class
87+
in the body of the interpreted subclass *does not* update the value of
88+
the native attribute. This leads to native and interpreted code observing
89+
different values of the attribute::
90+
91+
# native module
92+
from mypy_extensions import mypyc_attr
93+
94+
@mypyc_attr(allow_interpreted_subclasses=True)
95+
class Base:
96+
value = 1
97+
98+
def read_value(self) -> int:
99+
return self.value
100+
101+
# interpreted module
102+
from native import Base
103+
104+
class Child(Base):
105+
value = 98
106+
107+
obj = Child()
108+
print(obj.value) # 98
109+
print(obj.read_value()) # 1
110+
111+
When methods are marked `@final` in a native class that allows interpreted
112+
subclasses, mypyc assumes that no overrides are possible and optimizes calls
113+
to these methods. This means that if a subclass overrides a final method,
114+
calls through the compiled base class will still resolve to the base method::
115+
116+
# native module
117+
from typing import final
118+
from mypy_extensions import mypyc_attr
119+
120+
@mypyc_attr(allow_interpreted_subclasses=True)
121+
class Base:
122+
@final
123+
def name(self) -> str:
124+
return "base"
125+
126+
def call_name(self) -> str:
127+
return self.name()
128+
129+
# interpreted module
130+
from final_native import Base
131+
132+
class Child(Base):
133+
def name(self) -> str:
134+
return "child"
135+
136+
obj = Child()
137+
print(obj.name()) # child
138+
print(obj.call_name()) # base
139+
86140
You need to install ``mypy-extensions`` to use ``@mypyc_attr``:
87141

88142
.. code-block:: text

0 commit comments

Comments
 (0)