Stream: helpdesk (published)

Topic: ✔ PythonCall: How to call super class constructor?


view this post on Zulip Jesper Stemann Andersen (Aug 15 2023 at 14:26):

I am trying to use PythonCall.pytype to define a sub-class of a Python class - i.e. to define it using Julia code, but so far I can not figure out how to do the super().__init__(...) constructor call...

julia> using PythonCall

julia> Foo = pytype("Foo", (), [
           "__module__" => "__main__",
           pyfunc(
               name = "__init__",
               function (self, y = nothing)
                   self.y = y
                   return
               end,
           ),
           pyfunc(
               name = "__repr__",
               self -> "Foo($(self.y))",
           ),
       ])
Python: <class '__main__.Foo'>

julia> Bar = pytype("Bar", (Foo,), [
           "__module__" => "__main__",
           pyfunc(
               name = "__init__",
               function (self, x, y = nothing)
                   pyeval(Any, "super().__init__(y)", @__MODULE__, (self = self, y = y))
                   self.x = x
                   return
               end,
           ),
           pyfunc(
               name = "__repr__",
               self -> "Bar($(self.x), $(self.y))",
           ),
       ])
Python: <class '__main__.Bar'>

julia> Foo()
Python: Foo(None)

julia> Foo(1)
Python: Foo(1)

julia> Bar(2)
ERROR: Python: RuntimeError: super(): no arguments
...

Any tips?

view this post on Zulip Jesper Stemann Andersen (Aug 15 2023 at 14:38):

pybuiltins.super() seems promising...

julia> Bar = pytype("Bar", (Foo,), [
           "__module__" => "__main__",
           pyfunc(
               name = "__init__",
               function (self, x, y = nothing)
                   pybuiltins.super().__init__(y)
                   # pyeval(Any, "super().__init__(y)", @__MODULE__, (self = self, y = y))
                   self.x = x
                   return
               end,
           ),
           pyfunc(
               name = "__repr__",
               self -> "Bar($(self.y), $(self.y))",
           ),
       ])
Python: <class '__main__.Bar'>

julia> Bar(2)
ERROR: Python: RuntimeError: super(): __class__ cell not found
...

Likely related open Python bug: https://bugs.python.org/issue29944

view this post on Zulip Jesper Stemann Andersen (Aug 15 2023 at 14:44):

Solution:

julia> Bar = pytype("Bar", (Foo,), [
           "__module__" => "__main__",
           pyfunc(
               name = "__init__",
               function (self, x, y = nothing)
                   pybuiltins.super(self.__class__, self).__init__(y)
                   self.x = x
                   return
               end,
           ),
           pyfunc(
               name = "__repr__",
               self -> "Bar($(self.x), $(self.y))",
           ),
       ])
Python: <class '__main__.Bar'>

julia> Foo()
Python: Foo(None)

julia> Foo(1)
Python: Foo(1)

julia> Bar(2)
Python: Bar(2, None)

julia> Bar(2, 3)
Python: Bar(2, 3)

view this post on Zulip Notification Bot (Aug 15 2023 at 14:46):

Jesper Stemann Andersen has marked this topic as resolved.


Last updated: Oct 02 2023 at 04:34 UTC