functions without parentheses

bruno modulix onurb at xiludom.gro
Thu Jul 28 18:22:57 CEST 2005


Jerry He wrote:
> Hi, 
>   Is it possible to create a function that you can use
> without parenthesizing the arguments? for example, for
> 
> def examine(str):
>      .....
>      .....
> 
> Is there some way to define it so that I can call it
> like
> 
> examine "string" 
> instead of examine("string")? 

No.

The reason (well, one of the reasons) is that, given a function my_func

def my_func(*args, **kwargs):
  print "in my_func:"
  print "+ args : %s" % ", ".join(args)
  print "+ kwargs %s" % ", ".join(["%s=%s" % keyval \
                                   for keyval in kwargs.items()])
  return True


the expressions

  my_func
and
  my_func()

have very different semantics. (hint: copy/paste this code in your
python interactive interpreter).

The first expression has exactly the same semantic as it would have with
any other object[1] : it returns a reference to the function object
referenced by the name 'my_func' according to namespace rules.

[1] remember, in Python, functions are objects too.


The second expression has the usual 'function call' semantic.

The first expression allow to write code like:
  my_func_alias = my_func
  my_func_alias()

or
  def my_caller_func(any_func, *args, **kwargs):
    print "calling %s with *args %s and **kwargs %s" \
           % (any_func,
              ", ".join(args),
              ", ".join(["%s=%s" % keyval for keyval in kwargs.items()])

    result = any_func(*args, **kwargs)
    print "result :%s" % result
    return result

  my_caller_func(my_func)


In fact, '()' is the 'call' operator, that is then applied to the
callable object[2] referenced by 'my_func'. So a function call like

  my_func()

is in fact made in two steps:
- retrieving the object referenced by the name 'my_func'
- trying to apply the '()' call operator on it.


[2] Functions are just one special case of callable object. Lambda are
another, as any instance of a class defining the __call__ method.


the call operator could be implemented like this:
def __call_op__(func_name, *args, **kwargs):
   if hasattr(func_name, __call__):
	return func_name.__call__(*args, **kwargs)
   else:
        raise TypeError("%s object is not callable" % type(func_name))


Ok. Now that you know this, if Python was to support the

  result = my_func "arg1", "arg2"

syntax, how should the expression

  result = my_func

be interpreted ?-)

(hint: remember that the prototype of my_func allow us to call it with
no args at all)

There are good reasons for trying to have a clear and unambigous syntax.
functions-being-objects (as wall as 'other-objects-being-callable) is
one of the strength of Python, and it's a common idiom in Python to pass
functions (or any other callable) around.

BTW, note that there are few languages that doesn't inforce one (and
only one) unambigous syntax for function calls (even VB has a defined
and mandatory syntax for function calls, which is the same as Python's.
What VB has that Python has not is the semantic difference between
functions and procedures, and different syntaxes for both).


HTH
-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list