rstudio / reticulate

R Interface to Python
https://rstudio.github.io/reticulate
Apache License 2.0
1.68k stars 328 forks source link

Feature Request: Import Module as S3 #666

Open jtelleriar opened 4 years ago

jtelleriar commented 4 years ago

When importing a Python module:

Could this be imported as an S3 object?

library(reticulate)
os <- import("os")

There are libraries that convert from R6 to S3 that could be helpful:

https://cran.r-project.org/web/packages/R62S3/index.html

kevinushey commented 4 years ago

Why? I don't see a strong motivation to do so.

jtelleriar commented 4 years ago

Method dispatch

El jue., 12 dic. 2019 18:35, Kevin Ushey notifications@github.com escribió:

Why? I don't see a strong motivation to do so.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/rstudio/reticulate/issues/666?email_source=notifications&email_token=AHA4WJZDVC452MFQBJQ2N6TQYJY6VA5CNFSM4JZNVPUKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEGXN2QA#issuecomment-565108032, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHA4WJ3QCC7E6IN3KLLP4BLQYJY6VANCNFSM4JZNVPUA .

jtelleriar commented 4 years ago

For a given class, it would allow from R, and from an interactive session perspective, either method chaining, or function chaining (With pipes %>%), irrespectively.

@jjallaire May you share your viewpoint about enabling optional S3 method dispatch?

Marlin-Na commented 4 years ago

@jtelleriar I guess you want to expose the python's module namespace to R?

Then why not simply do the following:

library(reticulate)

attach_py_module <- function(name) {
    module <- import(name)
    attrs <- py_list_attributes(module)
    env <- new.env()
    for (attr in attrs) {
        assign(attr, module[attr], envir = env)
    }
    attach(env, name = paste0("pymodule:", name))
}

detach_py_module <- function(name) {
    attachname <- paste0("pymodule:", name)
    while(attachname %in% search())
        detach(attachname, character.only = TRUE, unload = TRUE)
}

attach_py_module("sympy")
# The following objects are masked from package:stats:
#     
#     binomial, C, decompose, fft, integrate, poly, reshape, rf, var
# 
# The following objects are masked from package:graphics:
#     
#     lcm, plot, symbols
# 
# The following objects are masked from package:base:
#     
#     acos, acosh, asin, asinh, atan, atan2, atanh, beta, ceiling,
# cos, cosh, det, diag, diff, digamma, exp, factor, factorial,
# floor, gamma, log, Mod, ordered, pi, pretty, prod, sequence,
# sign, sin, sinh, solve, source, sqrt, tan, tanh, trace,
# trigamma, trunc

Add(sympify("x"), 42L)
# x + 42

detach_py_module("sympy")

Though it might be useful to add something similar to reticulate. @kevinushey Any opinion?

jtelleriar commented 4 years ago

Yes, but when given a specific class object, it shall only be done for associated methods, not for remaining object's attributes.

jtelleriar commented 4 years ago

And "import" function could have an argument which allows doing so directly within the function itself.

kevinushey commented 4 years ago

My opinion is that this is not reticulate's job -- it should be viewed as a lower-level interface to Python, which other R packages can build upon and provide their own interfaces for as desired.

jtelleriar commented 4 years ago

For me, it depends:

Sometimes you may want a higher level interface, with S3-like method dispatch.

And others, for a lower level development (Eg: A Package), a R6-like object oriented class might work better.

jtelleriar commented 4 years ago

Another interesting option would be to import within reticulate's namespace, magrittr's "exposition pipe operator": %$%

https://cran.r-project.org/web/packages/magrittr/magrittr.pdf

Easy and fast! ;)