Reputation: 15399
This is in reference to Python 3.2. Pertinent grammar rules are as follows (http://docs.python.org/py3k/reference/grammar.html):
power: atom trailer* ['**' factor]
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
According to this a basic function call could look like:
atom '(' ')'
But I believe we can't just put any atom
in there. For example, even though 1
is an atom
(NUMBER
), 1
is not a function and therefore you cannot call it with something like 1()
. My question is: given an instance of the power
grammar rule, could its atom
be substituted with any rule of atom
's other than NAME
in a parse tree of a Python program and still run?
EDIT (ANSWER):
Anything that is "callable" may be called with the ()
operator. (http://docs.python.org/py3k/reference/expressions.html#calls):
call ::= primary "(" [argument_list [","] | comprehension] ")"
The
primary
must evaluate to a callable object (user-defined functions, built-in functions, methods of built-in objects, class objects, methods of class instances, and all objects having a__call__()
method are callable).
This means you can do stuff like:
>>> eval.__call__.__call__("print(\"x\")")
x
Or even crazier (useless) stuff:
>>> a = lambda x : [abs, lambda y : y][0 if x < 0 else 1](x)
>>> a(1)
1
>>> a(-1)
1
>>> a(0)
0
Upvotes: 1
Views: 884
Reputation: 71485
A parenthesised sub-expression is also callable, because it may be a function, even without containing a name: (lambda: 1)()
. Looking at the grammar I can't actually tell exactly how that's parsed (it doesn't seem to be either a yield_expr
or a testlist_comp
, but I can't see anything other than an atom
that's valid to stick call-parentheses after either).
Regardless though, it's not the job of the parser to enforce semantic checks. 1()
is perfectly able to be interpreted as an attempt to call the number 1 with no arguments; whether that means anything or not is up to the interpreter. Parser failures are for cases when the interpreter isn't able to figure out what operations the code is requesting to even attempt to carry them out.
Singling out NAME
as the only thing that's legal to have a function call trailer would add unnecessary complexity to the grammar for little real benefit. Python already has a perfectly good mechanism for reporting the error of trying to call something that can't be called, and that mechanism is a runtime exception. The runtime exception would always have to exist because there are plenty of names bound to things that are not callable, so it's just less conceptual overhead to use the same mechanism everywhere.
It would be a bit counter-intuitive at the level of the Python programmer, too. In my internalised way of thinking about Python syntax, there are other things that aren't syntactically names that are perfectly reasonable to call, such as the following:
result()()
dict_of_funcs[name]()
It just so happens that none of these are parsed as an atom
(because they're rather parsed as a single atom
followed by multiple trailer
s) but that's not how I think about the Python language, I just think "you can call anything that's an expression" (modulo precedence rules that may require the addition of parentheses), and under that understanding I would be surprised to be unable to call an integer or a string (especially since I can when it's a name rather than a literal).
It would also make changing the language semantics more difficult. Imagine a hypothetical future change to the language where calling a dictionary is defined to be the same as looking up a key, so that I could write {1: 'foo'}(1)
. Under the current grammar, all that would be necessary would be to implement the equivalent of __call__
for the built-in dict
type. If only NAME
and not other atoms could have the '(' [arglist] ')'
trailer, then this would introduce an inconsistency where a literal dict
value could not be called, but a name bound to a dict
value could be called. An inconsistency much like that already exists where x.__class__
is fine but 1.__class__
is not, but that's basically just compromise due to the existence of floating point literals like 1.0
. There's no similar case for making 1()
invalid syntax rather than just an exception-raising operation.
Upvotes: 0
Reputation: 526613
>>> 1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
>>>
Notice that the error here is a TypeError
and not a SyntaxError
. It is perfectly legal syntax to try to call a number; numbers just don't have any actual call functionality.
Upvotes: 7