question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cython functions not bound as methods

See original GitHub issue

In Python, one can do

class A:
    pass

def foo(self):
    print self

A.foo = foo
print A().foo()

and foo will get bound as expected. However, Cython creates PyCFunctions which do not properly bind when accessed (possibly by design). This is the root issue behind http://trac.cython.org/ticket/478, and will become more evident once closures start getting used.

PyCFunction does not allow subclassing. The only reasonable fix I see is to create a new type that wraps PyCFunction but behaves like PyFunction. This will have indirection overhead. To avoid overhead, one alternative is for our new type to have the same struct and slots as PyCFunction (with the exception of tp_name, tp_descr_get, tp_alloc, and tp_dealloc of course). This still may have overhead as the Python compiler optimizes for PyCFunction calls–perhaps the user should be allowed to control this (as part of an “ultra pure, I don’t care what cost” mode…)?

Migrated from http://trac.cython.org/ticket/494

Issue Analytics

  • State:closed
  • Created 14 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
robertwbcommented, Aug 16, 2016

bfroehle changed cc to bfroehle commented

I’ve run into this before and have also asked about it on StackOverflow. In general it’s pretty easy to work around in Python 2:

A.foo = types.MethodType(foo, None, A)

But somewhat troublesome in Python 3. The best suggestion I got was:

A.foo = functools.update_wrapper(lambda *a, **kw: foo(*a, **kw), foo)

It’s a weird gotcha, but engineering a workaround without introducing performance penalties is likely difficult (if not impossible). Perhaps the best option is just to document it and move on.

0reactions
robertwbcommented, Aug 16, 2016

scoder changed description from

In Python, one can do

class A:
    pass

def foo(self):
    print self

A.foo = foo
print A().foo()

and foo will get bound as expected. However, Cython creates PyCFunctions which do not properly bind when accessed (possibly by design). This is the root issue behind http://trac.cython.org/ticket/478, and will become more evident once closures start getting used.

PyCFunction does not allow subclassing. The only reasonable fix I see is to create a new type that wraps PyCFunction but behaves like PyFunction. This will have indirection overhead. To avoid overhead, one alternative is for our new type to have the same struct and slots as PyCFunction (with the exception of tp_name, tp_descr_get, tp_alloc, and tp_dealloc of course). This still may have overhead as the Python compiler optimizes for PyCFunction calls–perhaps the user should be allowed to control this (as part of an “ultra pure, I don’t care what cost” mode…)?

to

In Python, one can do

class A:
    pass

def foo(self):
    print self

A.foo = foo
print A().foo()

and foo will get bound as expected. However, Cython creates PyCFunctions which do not properly bind when accessed (possibly by design). This is the root issue behind http://trac.cython.org/ticket/478, and will become more evident once closures start getting used.

PyCFunction does not allow subclassing. The only reasonable fix I see is to create a new type that wraps PyCFunction but behaves like PyFunction. This will have indirection overhead. To avoid overhead, one alternative is for our new type to have the same struct and slots as PyCFunction (with the exception of tp_name, tp_descr_get, tp_alloc, and tp_dealloc of course). This still may have overhead as the Python compiler optimizes for PyCFunction calls–perhaps the user should be allowed to control this (as part of an “ultra pure, I don’t care what cost” mode…)? resolution to fixed status from new to closed commented

This works with the “binding=True” directive, which is now (since 0.17 IIRC) on by default for .py files.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cython callback works correctly for function, but not for bound ...
A totally different bound method is being called. However, when I make OnDrillButtonPress a static method, <function OnDrillButtonPress at ...
Read more >
Cython callback works correctly for function ... - Google Groups
implemented a callback system that works with normal functions but fails strangely when passing in bound methods. Here is a portion of my...
Read more >
Language Basics — Cython 3.0.0a11 documentation
However with Cython it is possible to gain significant speed-ups through the use of 'early binding' programming techniques. Providing static typing to ...
Read more >
Introduction to Cython for Solving Differential Equations
Nevertheless, we do not want these calls to be hardcoded for a special choice of problem and method. In C one would have...
Read more >
inspect — Inspect live objects — Python 3.11.1 documentation
number of keyword only arguments (not including ** arg). co_name ... Return True if the object is a built-in function or a bound...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found