[Python-Dev] Extended Function syntax

Gerald S. Williams gsw@agere.com
Wed, 29 Jan 2003 15:10:51 -0500


Guido van Rossum wrote:
> The problem is that this is a *very* radical change to the grammar,
> and I'm not sure I can rigorously define how the switch from
> "expression parsing mode" to "block parsing mode" should work.

I've started to compose this e-mail three times,
and I keep running into counter-examples. I'll
try to keep this consistent...

I can see your point. What happens as soon as you
try to do something like this?

 class Foo(object):
     myprop1, myprop2 = property:
         ...
     , property: ...

Although at least in this case, the following
trick could suffice:

 class Foo(object):
     myprop1, myprop2 = (
         property:
            ...
         ), # block end: indent == property: line
         property: ...
     # block end: indent < property: line
     myprop3 = property:
         ...
     # block end: indent == property: line
     ...

That example may be contrived (and it's solved
anyway), but perhaps it demonstrates one of the
dimensions in which this impacts the grammar.
There must be similar situations to consider.

And once you open the door for code blocks of this
type, I think improving on lambda is a natural next
step (or perhaps the first step :-) ). The solution
reached here is likely to have further-reaching
consequences.

So perhaps I should drag out an implementation that
uses a lambda replacement:

 class Parrot(object):
     count = property(*mu(""":
         "Treat mostly-parrots as full parrots."
         def Get(self): return self._count
         def Set(self,count): self._count = int(round(count))
         def Del(self): self._count = 0
         return Get,Set,Del,"Current parrot count"
     """)())

 def mu(*code):
     """For when lambda doesn't hack it"""
     splitcode = "".join(map(str,code)).split(":")
     args = splitcode[0]
     code = ":".join(splitcode[1:])
     return mucode(args,code)

 def mucode(args, code):
     exec "def mucode(" + args + "):" + code + "\n"
     return mucode

That could be easily morphed into something like
this (under the hood, propertymethods() could have
it's way with class or perform whatever other evil
incarnations are needed):

 class Parrot(object):
     count = propertymethods("""
         "Current parrot count"
         def __get__(self): return self._count
         def __set__(self,count): self._count = int(round(count))
         def __del__(self): self._count = 0""")

But you still have the issue of marking where the
block ends and of allowing other things to follow
it on the same "line". Is the parentheses trick I
initially showed sufficient in all cases?

If it is, one solution that wouldn't be too far
removed from the current version is to add a
standard construct that encapsulates a block of
code (if need be, it could return it as text).
Then property() could do something special if it
saw such a block:

 class Parrot(object):
     count = property(codeblock:
         "Current parrot count"
         def __get__(self): return self._count
         def __set__(self,count): self._count = int(round(count))
         def __del__(self): self._count = 0
     )

Of course, if you make property a keyword, you
could go a step further:

 class Parrot(object):
     count = property codeblock:
         "Current parrot count"
         def __get__(self): return self._count
         def __set__(self,count): self._count = int(round(count))
         def __del__(self): self._count = 0

In the end, this doesn't look that different,
does it? But I think separating the notion of
"codeblock" from the notion of "property" is
a good idea regardless.

-Jerry