Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Status: Partially implemented. See pure.

It would be nice to be able to express Cython semantics (i.e. everything the cdef keyword is used for) in such a way that the resulting code is valid Python. The most obvious way of doing this is with decorators (I would like to avoid hiding stuff in comments and/or strings). Type inference should make this easier.

StefanBehnel: Part of this can be achieved with PEP 3107. The exceptions I see are: "cdef class" and "cdef type variable". Class decorators would work (and could even express better semantics than the current "C, but Python visible"). Variable decorators do not exist anyway.

There are three increasingly attractive levels of doing this.
  1. It is syntactically valid but won't run.
  2. It runs, but ignores all type declarations.
  3. It runs, using ctypes to do exactly what it would when compiled.

Perhaps one would want to alternate between 2 and 3.

Pros

  • Lots of Python development tools (profiling, lint, etc)
  • Faster debug cycle (no c compile step)
  • Possibly easier code conversion
  • Lower learning curve for Python users who wants to type a few parts of their code for speed but doesn't want to know anything about the C part? Also simply higher consistency in general for anybody using Cython primarily as a language in it's own right rather than for wrapping. (DagSverreSeljebotn, 2008-03-07)

Cons

  • Violate the "one way" of doing things mantra of Python
  • May be harder to express some things
  • What we have works well
  • Might conflict with the behaviour users expect (see comment section)

Another idea:

What if there were a @cython decorator such that one places it in a pure Python file which takes the function, compiles it, and returns the resulting compiled function.

Comments

DagSverreSeljebotn: I originally supported this heavily but have come to a different conclusion now. The problem is that Cython has an approach of typed variables, which Python does not, and a Python coder will therefore make different assumptions about what code should do. Consider this example:

def test(x: cython.types.int):
  print x
  x = 2.34
  print x

Cython thinking is then to do like C++ and coerce the type and print "2" the second time. This is in deep contrast with an ingrown assumption when coding in Python that assigning pure variables only copies the reference and has no side-effects (though with fields it is different, one can override __setattr__).

Because of this, I think "magic variables that have side-effects when assigned to" (like, what is completely normal in typed languages, but it is still abnormal in Python) at least should have a custom, non-Python syntax when declared.

Pure Python syntax only could still be supported by using type coercion though.

Robertwb: The case above would result in a compile-time error, the only "conversion-on-assignments" that happen automatically are ones that are non-destructive.

DagSverreSeljebotn: Looks like I'm assuming too much now and then (regarding locals() as well), I'll try to be more careful. (Of course, I should have known, that's kind of the way it is in C when I just stop and think about it.)

MarkLodato: To address the above concerns, what about having a single Python object containing all the C variables? Then you can use __setattr__ in Python to achieve the same effects as in Cython. For example:

def test(x : cython.types.int):
    c = cython.c_var(
        i = cython.types.int,
        f = cython.types.float
        )
    c.i = x    # OK
    c.f = x    # ERROR

The downside would be that all your C variables have an annoying "c." prefix. I'm not sure how to use this to fix the problem with function arguments ("x" in this case).

Edit: For the function arguments, you could pass everything as a single c_var and then have a decorator that packs the arguments for the caller. For example:

@cython.function({'x' : cython.types.int})
def test(args : cython.c_var):
    c = cython.c_var(
        i = cython.types.int,
        f = cython.types.float
        )
    c.i = args.x    # OK
    c.f = args.x    # ERROR
    args.x = 3.14   # ERROR

It's ugly, but I think it might work...

Something went wrong with that request. Please try again.