Consider following Cython code:
import cython
@cython.final
cdef class Fish:
cdef double weight
cdef class Aquarium:
cdef Fish fish
cpdef double fish_weight(Fish fish):
return fish.weight
cpdef void change_fish_weight(Fish fish, double weight):
fish.weight = weight
cpdef double new(double weight):
cdef Fish f = Fish()
f.weight = weight
return f.weight
cdef Aquarium aq = Aquarium()
cdef Fish fish = Fish()
change_fish_weight(fish, 5.0)
fish_weight(fish)
new(5.0)
Fish
allocated inline in aq
?fish
"passed by reference" to change_fish_weight
?fish
"passed by reference" to fish_weight
?f
allocated on stack in new
function? (Let's suppose optimizer won't entirely eliminate variable f
as needless.)Fish
was struct and not extension type?Which answers change, if compiler optimization is enabled? Why?
Would be
Fish
allocated inline inaq
?
No
Would be
fish
"passed by reference" tochange_fish_weight
?
Yes
Would be
fish
"passed by reference" tofish_weight
?
Yes
Would be
f
allocated on stack innew
function? (Let's suppose optimizer won't entirely eliminate variablef
as needless.)
No.
What about previous question if
Fish
was struct and not extension type?
A struct would be allocated on the stack.
Which answers change, if compiler optimization is enabled? Why?
None of the answers change.
--------------------------------------------
Essentially final extension types are still Python objects and so are still heap allocated because they have to be passed around by reference like any other Python object. This answer explains the reasons to use final extension types - they're relatively small optimizations and have nothing to do with stack allocation.