Search code examples
pythoncythonstatic-typing

How can I set a mutable variable in C extensions which takes another C extension as input?


Let's suppose that there are some classes like these ones:

cdef class parent:
  cdef public:
    int trait1
  def __init__(self, num1):
    self.trait1 = num1

cdef class child(parent):
  cdef public:
    int trait2
  def __init__(self, num1, num2):
    super().__init__(num1)
    self.trait2 = num2

cdef class new_parent:
  cdef public:
    float new_trait
  def __init__(self, num):
    self.new_trait = num

Now I want to have another class like this one:

cdef class gui:
  cdef public:
    parent agent
  def __init__(self, agent):
    self.agent = agent
  def change_parent(self, new_agent): # new_agent could be any of [child, parent, new_parent]
    self.agent = new_agent
    print(self.module)

In gui class I declare a variable which could get a class as input (between [parent, new_parent, child]). The problem is that if I want to change the gui.agent to another class in gui.change_parent function, this error occurs:

TypeError: Cannot convert _cython_magic_b6858e13e41432c14dc63fbb10e81472.new_parent to _cython_magic_b6858e13e41432c14dc63fbb10e81472.parent

I had developed the same code in python but such error never happened because I don't need to static-type the class variables. so what should I do to be able to modify the gui.agent to another classes in cython? Is there any solution for this?


Solution

  • You define the type of agent to be parent, which allows it to be parent or any derived type. new_parent is not of type parent and does not derive from parent so can't be assigned to agent.

    You either need to make new_parent inherit from parent, or you need to remove the type specifier on agent so that it can accept any Python object (e.g. object agent).

    What you can't do is specify a fixed Cython type for a variable, and then hope to be able to assign any arbitrary type to that variable.