Skip to content

Commit

Permalink
Defining Python classes (@PyDEF)
Browse files Browse the repository at this point in the history
  • Loading branch information
cstjean committed Apr 8, 2016
1 parent a9eaccf commit 453100f
Show file tree
Hide file tree
Showing 8 changed files with 345 additions and 332 deletions.
57 changes: 57 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,63 @@ For example, calling `f(x, function=g)` will fail because `function` is
a reserved word in Julia. In such cases, you can use the lower-level
Julia syntax `f(x; :function=>g)`.

### Defining Python Classes

`@pydef` creates a Python class whose methods are implemented in Julia.
For instance,

@pyimport numpy.polynomial as P

@pydef type Doubler <: P.Polynomial
__init__(self, x=10) = (self[:x] = x)
my_method(self, arg1=5) = arg1 + 20 # the right-hand-side is Julia code
x2.get(self) = self[:x] * 2
x2.set!(self, new_x::Int) = (self[:x] = new_x / 2)
end

Doubler()[:x2]

is equivalent to

class Doubler(numpy.polynomial.Polynomial):
def __init__(self, x=10):
self.x = x

def my_method(self, arg1):
return arg1 + 20

@property
def x2(self): return self.x * 2

@x2.setter
def x2(self, new_val):
self.x = new_val / 2

The methods' arguments and return values are automatically converted. All Python
special methods are supported (__len__, __add__, etc.)

`@pydef` allows for multiple-inheritance of Python types:

@pydef type SomeType <: (BaseClass1, BaseClass2)
...
end

Here's another example using [Tkinter](https://wiki.python.org/moin/TkInter)

using PyCall
@pyimport Tkinter as tk

@pydef type SampleApp <: tk.Tk
__init__(self, args...; kwargs...) = begin
tk.Tk[:__init__](self, args...; kwargs...)
self[:label] = tk.Label(text="Hello, world!")
self[:label][:pack](padx=10, pady=10)
end
end

app = SampleApp()
app[:mainloop]()

### GUI Event Loops

For Python packages that have a graphical user interface (GUI),
Expand Down
1 change: 1 addition & 0 deletions REQUIRE
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ julia 0.4
Compat 0.7.9
Dates
Conda 0.1.6
MacroTools 0.2
8 changes: 3 additions & 5 deletions src/PyCall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export pycall, pyimport, pybuiltin, PyObject,
pyerr_check, pyerr_clear, pytype_query, PyAny, @pyimport, PyDict,
pyisinstance, pywrap, pytypeof, pyeval, PyVector, pystring,
pyraise, pytype_mapping, pygui, pygui_start, pygui_stop,
pygui_stop_all, @pylab, set!, PyTextIO, @pysym, PyNULL
pygui_stop_all, @pylab, set!, PyTextIO, @pysym, PyNULL, @pydef

import Base: size, ndims, similar, copy, getindex, setindex!, stride,
convert, pointer, summary, convert, show, haskey, keys, values,
Expand Down Expand Up @@ -142,6 +142,7 @@ PyObject(o::PyPtr, keep::Any) = pyembed(PyObject(o), keep)
include("pybuffer.jl")
include("conversions.jl")
include("pytype.jl")
include("pyclass.jl")
include("callback.jl")
include("io.jl")

Expand Down Expand Up @@ -593,14 +594,11 @@ end
# for the reasons described in JuliaLang/julia#12256.

precompile(jl_Function_call, (PyPtr,PyPtr,PyPtr))
precompile(pyio_repr, (PyPtr,))
precompile(pyjlwrap_dealloc, (PyPtr,))
precompile(pyjlwrap_repr, (PyPtr,))
precompile(pyjlwrap_hash, (PyPtr,))
precompile(pyjlwrap_hash32, (PyPtr,))

for f in (jl_IO_close, jl_IO_fileno, jl_IO_flush, jl_IO_isatty, jl_IO_readable, jl_IO_writable, jl_IO_readline, jl_IO_readlines, jl_IO_seek, jl_IO_seekable, jl_IO_tell, jl_IO_writelines, jl_IO_read_text, jl_IO_read, jl_IO_readall_text, jl_IO_readall, jl_IO_readinto, jl_IO_write)
precompile(f, (PyPtr,PyPtr))
end
# TODO: precompilation of the io.jl functions

end # module PyCall
Loading

0 comments on commit 453100f

Please sign in to comment.