3

The R package reticulate has a custom $ operator which acts as the . operator in the equivalent Python modules/objects. Since the second argument of $ cannot be evaluated, how do you pass an argument to it in this scenario?

The example usage on the reticulate README is

library(reticulate)
os <- import("os")
os$chdir("tests")
os$getcwd()

I'm after the following function where ... would be the python call with zero or more arguments.

my_function <- function(python_object, ...)

The python_object needs to be of class python.builtin.object or python.builtin.module and the arguments would need to be passed as characters since the functions don't exist in the global environment.

eg.

my_function(os, "chdir", "tests")
my_function(os, "getcwd")
my_function(r_to_py("my_string"), "lstrip", "my_")

My thoughts were something along the lines of

do.call("chdir", list("tests"), envir = os)

or

reticulate:::`$.python.builtin.object`(os, eval(parse(text="chdir('tests')")))

however neither of these have worked.

ruaridhw
  • 2,305
  • 8
  • 22

1 Answers1

2

Was achieved much simpler than I imagined...

my_function <- function(python_module, attribute, ...) {
  py_call(python_module[[attribute]], ...)
}

In general, $ is shorthand for [[.


Update

@jjallaire pointed out...

py_call is a lower level function which doesn't currently get the benefit of type wrapping (but it certainly should).

To return identical output (ie inherits the correct classes) as $ use either:

  • do.call(python_module[[attribute]], args = list(function_args))
  • python_module[[attribute]](function_args)

instead of py_call

See rstudio/reticulate#149.

ruaridhw
  • 2,305
  • 8
  • 22