Python equivalent of Ruby's 'method_missing'
There is no difference in Python between properties and methods. A method is just a property, whose type is just instancemethod
, that happens to be callable (supports __call__
).
If you want to implement this, your __getattr__
method should return a function (a lambda
or a regular def
, whatever suite your needs) and maybe check something after the call.
Ruby’s “method_missing” in Python
As others have mentioned, in Python, when you execute o.f(x)
, it's really a two-step operation: First, get the f
attribute of o
, then call it with parameter x
. It's the first step that fails because there is no attribute f
, and it's that step that invokes the Python magic method __getattr__
.
So you have to implement __getattr__
, and what it returns must be callable. Keep in mind, if you also try to get o.some_data_that_doesnt_exist
, the same __getattr__
will be called, and it won't know that it's a "data" attribute vs. a "method" that being sought.
Here's an example of returning a callable:
class MyRubylikeThing(object):
#...
def __getattr__(self, name):
def _missing(*args, **kwargs):
print "A missing method was called."
print "The object was %r, the method was %r. " % (self, name)
print "It was called with %r and %r as arguments" % (args, kwargs)
return _missing
r = MyRubylikeThing()
r.hello("there", "world", also="bye")
produces:
A missing method was called.
The object was <__main__.MyRubylikeThing object at 0x01FA5940>, the method was 'hello'.
It was called with ('there', 'world') and {'also': 'bye'} as arguments
Are there equivalents to Ruby's method_missing in other languages?
Some use cases of method_missing
can be implemented in Python using __getattr__
e.g.
class Roman(object):
def roman_to_int(self, roman):
# implementation here
def __getattr__(self, name):
return self.roman_to_int(name)
Then you can do:
>>> r = Roman()
>>> r.iv
4
Numeric class and method missing
puts
handles arrays in a special way. Therefore, puts 5
attempts to call 5.to_ary
and when implementing method_missing
, it calls it with an argument of :to_ary
.
Within method_missing
you call puts self
which is equivalent to puts 5
. This is a recursion which Ruby shows as [...]
.
This recursive array produces the same output:
ary = []
#=> []
ary << ary
#=> [[...]]
method_missing equivalent in R
For the access a$b
, yes, this is possible – if messy. The reason is that $
is just an operator that we can redefine.
The default definition can be retrieved as follows:
> `$`
.Primitive("$")
It’s easy enough possible to change this so that we first test whether the b
in a$b
actually exists. Here’s a rough outline (but only a rough outline, see below):
`$` <- function (a, b) {
if (exists(as.character(substitute(b)), where = a))
.Primitive("$")(a, b)
else
methodMissing(as.character(substitute(a)), as.character(substitute(b)))
}
… now we just need to supply methodMissing
:
methodMissing <- function (a, b)
cat(sprintf('Requested missing %s on %s\n', b, a))
… and we can use it:
> foo <- list(bar = 'Hello')
> foo$bar
[1] "hello"
> foo$baz
Requested missing baz on foo
However, note that this breaks in interesting ways for other types – for instance, it no longer works with data frames:
> cars$speed
NULL
I don’t know whether it’s trivial to fix this – it’s not enough to test for is.list(a)
, for instance – so proceed with caution.
The solutions for S3 and S4 are left as an exercise for the reader (actually, I have no clue – I don’t use S4 and rarely use S3).
Does Javascript have something like Ruby's method_missing feature?
The ruby feature that you are explaining is called "method_missing" http://rubylearning.com/satishtalim/ruby_method_missing.htm.
It's a brand new feature that is present only in some browsers like Firefox (in the spider monkey Javascript engine). In SpiderMonkey it's called "__noSuchMethod__" https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/NoSuchMethod
Please read this article from Yehuda Katz http://yehudakatz.com/2008/08/18/method_missing-in-javascript/ for more details about the upcoming implementation.
Related Topics
How to Filter Only Printable Characters in a File on Bash (Linux) or Python
Problem Running Python from Crontab - "Invalid Python Installation"
Lxml Error "Ioerror: Error Reading File" When Parsing Facebook Mobile in a Python Scraper Script
Multi Platform Portable Python
Problems Adding Path and Calling External Program from Python
Set Bash Variable from Python Script
Python 3.5 Asyncio and Multiple Websocket Servers
Checking Running Python Script Within the Python Script
Unicodedecodeerror Reading Binary Input
Run Linux Grep Command from Python Subprocess
Creating a Symbolic in Shared Volume of Docker and Accessing It in Host MAChine
Why Does Loading the Libc Shared Library Have "'Libraryloader' Object Is Not Callable" Error
"Command Not Found" Using Line in Argument to Os.System Using Python
How to Install Writable Shared and User Specific Data Files with Setuptools
Using Python Subprocess.Call() to Launch an Ncurses Process
How to Run Python Script in Cron
How to Direct Output to a File When There Are Utf-8 Characters