[Python-Dev] Python keywords

Guido van Rossum guido@beopen.com
Mon, 28 Aug 2000 05:54:13 -0500


[Thomas Wouters]
> There was a thread here a few weeks ago (or so, I seem to have misplaced
> that particular thread :P) about using Python keywords as identifiers in
> some cases. You needed that ability for .NET-Python, where the specs say any
> identifier should be possible as methods and attributes, and there were some
> comments on the list on how to do that (by Guido, for one.)
> 
> Well, the attached patch sort-of does that. I tried making it a bit nicer,
> but that involved editing all places that currently use the NAME-type node,
> and most of those don't advertise that they're doing that :-S The attached
> patch is in no way nice, but it does work:
> 
> >>> class X:
> ...     def print(self, x):
> ...             print "printing", x
> ... 
> >>> x = X()
> >>> x.print(1)
> printing 1
> >>> x.print
> <method X.print of X instance at 0x8207fc4>
> >>> x.assert = 1
> >>>
> 
> However, it also allows this at the top level, currently:
> >>> def print(x):
> ...     print "printing", x
> ... 

Initially I thought this would be fine, but on second thought I'm not
so sure.  To a newbie who doesn't know all the keywords, this would be
confusing:

  >>> def try(): # my first function
  ...     print "hello"
  ...
  >>> try()
    File "<stdin>", line 1
      try()
	 ^
  SyntaxError: invalid syntax
  >>>

I don't know how best to fix this -- using different syntax for 'def'
inside a class than outside would require a complete rewrite of the
grammar, which is not a good idea.  Perhaps a 2nd pass compile-time
check would be sufficient.

> which results in some unexpected behaviour:
> >>> print(1)
> 1
> >>> globals()['print'](1)
> printing 1
> 
> But when combining it with modules, it does work as expected, of course:
> 
> # printer.py:
> def print(x, y):
>         print "printing", x, "and", y
> #
> 
> >>> import printer
> >>> printer.print
> <function print at 0x824120c>
> >>> printer.print(1, 2)
> printing 1 and 2
> 
> Another plus-side of this particular method is that it's simple and
> straightforward, if a bit maintenance-intensive :-) But the big question is:
> is this enough for what you need ? Or do you need the ability to use
> keywords in *all* identifiers, including variable names and such ? Because
> that is quite a bit harder ;-P

I believe that one other thing is needed: keyword parameters (only in
calls, not in definitions).  Also, I think you missed a few reserved
words, e.g. 'and', 'or'.  See Lib/keyword.py!

A comment on the patch: wouldn't it be *much* better to change the
grammar to introduce a new nonterminal, e.g. unres_name, as follows:

unres_name; NAME | 'for' | 'if' | 'while' | 'else' | 'elif' | 'def' | \
  'class' | 'print' | 'del' | 'raise' | 'exec' | 'in' | 'is' | 'from' | \
  'pass' | 'import' | 'global' | 'assert' | 'return' | 'break' | \
  'continue' | 'try' | 'except' | 'not' | 'lambda' | 'finally'

and use this elsewhere in the rules:

funcdef: 'def' unres_name parameters ':' suite
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' unres_name

Then you'd have to fix compile.c of course, but only in two places (I
think?).

--Guido van Rossum (home page: http://www.pythonlabs.com/~guido/)