pre-PEP: The create statement

S

Steven Bethard

The PEP below should be mostly self explanatory. I'll try to keep the
most updated versions available at:

http://ucsu.colorado.edu/~bethard/py/pep_create_statement.txt
http://ucsu.colorado.edu/~bethard/py/pep_create_statement.html



PEP: XXX
Title: The create statement
Version: $Revision: 1.4 $
Last-Modified: $Date: 2003/09/22 04:51:50 $
Author: Steven Bethard <[email protected]>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 05-Apr-2006
Python-Version: 2.6
Post-History: 05-Apr-2006


Abstract
========

This PEP proposes a generalization of the class-declaration syntax,
the ``create`` statement. The proposed syntax and semantics parallel
the syntax for class definition, and so::

create <callable> <name> <tuple>:
<block>

is translated into the assignment::

<name> = <callable>("<name>", <tuple>, <namespace>)

where ``<namespace>`` is the dict created by executing ``<block>``.
The PEP is based on a suggestion [1]_ from Michele Simionato on the
python-dev list.


Motivation
==========

Class statements provide two nice facilities to Python:

(1) They are the standard Python means of creating a namespace.
All statements within a class body are executed, and the resulting
local name bindings are passed as a dict to the metaclass.

(2) They encourage DRY (don't repeat yourself) by allowing the
class being created to know the name it is being assigned.

Thus in a simple class statement like::

class C(object):
x = 1
def foo(self):
return 'bar'

the metaclass (``type``) gets called something like::

C = type('C', (object,), {'x':1, 'foo':<function foo at ...>})

The class statement is just syntactic sugar for the above assignment
statement, but clearly a very useful sort of syntactic sugar. It
avoids not only the repetition of ``C``, but also simplifies the
creation of the dict by allowing it to be expressed as a series of
statements.

Historically, type instances (a.k.a. class objects) have been the
only objects blessed with this sort of syntactic support. But other
sorts of objects could benefit from such support. For example,
property objects take three function arguments, but because the
property type cannot be passed a namespace, these functions, though
relevant only to the property, must be declared before it and then
passed as arguments to the property call, e.g.::

class C(object):
...
def get_x(self):
...
def set_x(self):
...
x = property(get_x, set_x, ...)

There have been a few recipes [2]_ trying to work around this
behavior, but with the new create statement (and an appropriate
definition of property), the getter and setter functions can be
defined in the property's namespace like::

class C(object):
...
create property x:
def get(self):
...
def set(self):
...

The definition of such a property callable could be as simple as::

def property(name, args, namespace):
fget = namespace.get('get')
fset = namespace.get('set')
fdel = namespace.get('delete')
doc = namespace.get('__doc__')
return __builtin__.property(fget, fset, fdel, doc)

Of course, properties are only one of the many possible uses of the
create statement. The create statement is useful in essentially any
situation where a name is associated with a namespace. So, for
example, sub-modules could be created as simply as::

create module mod:
"This creates a sub-module named mod with an f1 function"

def f1():
...

and named, nested hierarchies like XML documents could be created
like::

create ETobject html:
"This statement would generate an ElementTree object"

create ETobject head:
"generate the head"
...

create ETobject body:
"generate the body"
...

If Python acquires interfaces, given an appropriately defined
``interface`` callable, the create statement can support interface
creation through the syntax::

create interface C(...):
...

which would mean that interface systems like that of Zope would no
longer have to abuse the class syntax to create proper interface
instances.


Specification
=============

Python will translate a create statement::

create <callable> <name> <tuple>:
<block>

into the assignment::

<name> = <callable>("<name>", <tuple>, <namespace>)

where ``<namespace>`` is the dict created by executing ``<block>``.
The ``<tuple>`` expression is optional; if not present, an empty tuple
will be assumed.

A patch is available implementing these semantics [3]_.


Optional Extensions
===================

Remove the create keyword
-------------------------

It might be possible to remove the create keyword so that such
statements would begin with the callable being called, e.g.:

module mod:
def f1():
...
def f2():
...

interface C(...):
...

However, this would probably add some complexity in the grammar and
so far I (Steven Bethard) have not been able to implement the feature
without the keyword.


Deprecating __metaclass__ in Python 3000
----------------------------------------

As a side-effect of its generality, the create statement mostly
eliminates the need for the ``__metaclass__`` attribute in class
objects. Thus in Python 3000, instead of::

class <name> <bases-tuple>:
__metaclass__ = <metaclass>
<block>

metaclasses could be supported by using the metaclass as the callable
in a create statement::

create <metaclass> <name> <bases-tuple>:
<block>

Removing the ``__metaclass__`` hook would simplify the BUILD_CLASS
opcode a bit.


References
==========

... [1] Michele Simionato's original suggestion
(http://mail.python.org/pipermail/python-dev/2005-October/057435.html)
... [2] Namespace-based property recipe
(http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442418)
... [3] Create Statement patch
(http://ucsu.colorado.edu/~bethard/py/create_stmt.patch)

Copyright
=========

This document has been placed in the public domain.



...
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
End:
 
P

Paul Rubin

I haven't looked at this enough to really understand it, but it looks
interesting and promising.
 
C

Carl Banks

Steven said:
This PEP proposes a generalization of the class-declaration syntax,
the ``create`` statement. The proposed syntax and semantics parallel
the syntax for class definition, and so::

create <callable> <name> <tuple>:
<block>

is translated into the assignment::

<name> = <callable>("<name>", <tuple>, <namespace>)

where ``<namespace>`` is the dict created by executing ``<block>``.
The PEP is based on a suggestion [1]_ from Michele Simionato on the
python-dev list.

And who needs a class statement after that?

create type A:
<block>

That's probably even more readable than class A, if not as familiar.
My biggest concern with this is the special arguments of the caller.
It breaks my heart that we couldn't do something like this:

create dict keymap:
A = 1
B = 2

And it'll probably confuse people as well. We ought to keep that in
mind.

Of course, properties are only one of the many possible uses of the
create statement. The create statement is useful in essentially any
situation where a name is associated with a namespace. So, for
example, sub-modules could be created as simply as::

create module mod:
"This creates a sub-module named mod with an f1 function"

def f1():
...

Let's not do this, really. A module should be one-to-one with a file,
and you should be able to import any module. Having in-line modules
complicates everything. And it becomes a misnomer. So, please, let's
get a better example. If you must, call it a scope or namespace.

Remove the create keyword
-------------------------

It might be possible to remove the create keyword so that such
statements would begin with the callable being called, e.g.:

module mod:
def f1():
...
def f2():
...

interface C(...):
...

I don't like it. It seems to violate the spirit of the pronouncement
on programmable syntax. I presume if it passes then "class" would
become a regular symbol and a synonym of "type".

Overall, it seems like an idea worth considering. In fact, I'd be in
favor of phasing out "class" in favor of "create type" in the interests
of there being only one obvious way to do it. (Obviously not before
Python 3000, though. The thing is, because the usage of "class" varies
so little, updating code to use "create type" would be pretty
automatic).

Carl Banks
 
P

Paddy

I wonder if the resulting code would look like Python.
It seems a great way to unify how things are defined, but I would not
want to mix the syntax with the current style.

- Pad.
 
B

bruno at modulix

Steven said:
The PEP below should be mostly self explanatory. I'll try to keep the
most updated versions available at:

http://ucsu.colorado.edu/~bethard/py/pep_create_statement.txt
http://ucsu.colorado.edu/~bethard/py/pep_create_statement.html



PEP: XXX
Title: The create statement
Version: $Revision: 1.4 $
Last-Modified: $Date: 2003/09/22 04:51:50 $
Author: Steven Bethard <[email protected]>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 05-Apr-2006
Python-Version: 2.6
Post-History: 05-Apr-2006


Abstract
========

This PEP proposes a generalization of the class-declaration syntax,
the ``create`` statement. The proposed syntax and semantics parallel
the syntax for class definition, and so::

create <callable> <name> <tuple>:
<block>

is translated into the assignment::

<name> = <callable>("<name>", <tuple>, <namespace>)

where ``<namespace>`` is the dict created by executing ``<block>``.
The PEP is based on a suggestion [1]_ from Michele Simionato on the
python-dev list.

Seems mostly clean. +1.

(and I do prefer it with the 'create' statement - more explicit and
readable than Michele's original proposition IMHO).
 
S

Serge Orlov

bruno said:
Steven said:
The PEP below should be mostly self explanatory. I'll try to keep the
most updated versions available at:
[snip]


Seems mostly clean. +1.

That's what Trojans said when they saw a wooden horse at the gates of
Troy ;)

Serge.
 
M

Michele Simionato

bruno said:
Seems mostly clean. +1.

(and I do prefer it with the 'create' statement - more explicit and
readable than Michele's original proposition IMHO).

Well, I do agree ;)

Actually, Steven's original PEP draft was closer to my original
proposal,
but I suggested him to propose the PEP with the 'create' keyword, just
to have a nicer title ;)

Michele Simionato
 
B

bruno at modulix

Serge said:
bruno said:
Steven said:
The PEP below should be mostly self explanatory. I'll try to keep the
most updated versions available at:

[snip]


Seems mostly clean. +1.


That's what Trojans said when they saw a wooden horse at the gates of
Troy ;)

<sardonic-laughter>he he he...</sardonic-laughter>
 
M

Michael Ekstrand

Carl said:
That's probably even more readable than class A, if not as familiar.
My biggest concern with this is the special arguments of the caller.
It breaks my heart that we couldn't do something like this:

create dict keymap:
A = 1
B = 2

Why couldn't you? Maybe I'm not reading carefully enough, but I didn't
see anything in the PEP prohibiting that. As long as dict knows how to
take arguments appropriately.

- Michael
 
M

Michael Ekstrand

Steven said:
The PEP below should be mostly self explanatory. I'll try to keep the
most updated versions available at:

http://ucsu.colorado.edu/~bethard/py/pep_create_statement.txt
http://ucsu.colorado.edu/~bethard/py/pep_create_statement.html



PEP: XXX
Title: The create statement
Version: $Revision: 1.4 $
Last-Modified: $Date: 2003/09/22 04:51:50 $
Author: Steven Bethard <[email protected]>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 05-Apr-2006
Python-Version: 2.6
Post-History: 05-Apr-2006
[large amount of crunchy goodness snipped]

+1 from me on this one.

Something it could be useful to try to add, if possible: So far, it
seems that this create block can only create class-like things (objects
with a name, potentially bases, and a namespace). Is there a natural way
to extend this to other things, so that function creation can be
modified? For example:

create tracer fib(x):
# Return appropriate data here
pass

tracer could create a function that logs its entry and exit; behavior
could be modifiable at run time so that tracer can go away into oblivion.

Given the current semantics of create, this wouldn't work. What would be
reasonable syntax and semantics to make something like this possible?

Maybe this would need to be a separate PEP. But it seems at least
somewhat related.

- Michael
 
T

Tim N. van der Leeuw

From what I read here it would make a huge useability improvement for
properties, and for that alone I would vote this a +1 if I were given
the right to vote.

Could this still make it in Python 2.5 even? If it's pushed hard
enough? I don't know if this has been discussed on the python-dev
mailing lists and what the reactions of python-devs and GvR was?

regards,

--Tim
 
M

Michele Simionato

Kay said:
Have you a rough estimation how many modules will be broken when
"create" is introduced as a keyword?

This is a very relevant question. I would expect the new keyword would
break lots
of modules. However measuring is better than speculating.

$ echo count_name.py
"""
Count the occurrences of a name in a Python script. For instance:

$ find /usr/lib/python2.4 -name \*.py | xargs python2.4 count_name.py
create
"""

import sys, tokenize, token

def count_name(name, script):
"Count the occurrences of a Python name in a script"
counter = 0
for tok_code, tok_value, (srow, scol), (erow, ecol), line in \
tokenize.generate_tokens(file(script).readline):
if tok_code == token.NAME and tok_value == name:
counter += 1
print 'line %s: %s' %(srow, line),
if counter: print '*** %s ***\n' % script
return counter

if __name__ == '__main__':
name = sys.argv[1]
scripts = sys.argv[2:]
total = sum(count_name(name, script) for script in scripts)
print 'Found %d occurrences of %r' % (total, name)

Here is the output on my box:

line 132: def __init__(self, filename, dbhome, create=0,
truncate=0, mode=0600,
line 140: if create:
*** /usr/lib/python2.4/bsddb/dbtables.py ***

line 312: def get_finalized_command (self, command, create=1):
line 318: cmd_obj = self.distribution.get_command_obj(command,
create)
*** /usr/lib/python2.4/distutils/cmd.py ***

line 828: def get_command_obj (self, command, create=1):
line 835: if not cmd_obj and create:
*** /usr/lib/python2.4/distutils/dist.py ***

line 379: def create(self, mailbox):
*** /usr/lib/python2.4/imaplib.py ***

line 1569: self.tk = _tkinter.create(screenName, baseName,
className, interactive, wantobjects, useTk, sync, use)
*** /usr/lib/python2.4/lib-tk/Tkinter.py ***
 
S

Steven Bethard

Michael said:
Something it could be useful to try to add, if possible: So far, it
seems that this create block can only create class-like things (objects
with a name, potentially bases, and a namespace). Is there a natural way
to extend this to other things, so that function creation can be
modified? For example:

create tracer fib(x):
# Return appropriate data here
pass

tracer could create a function that logs its entry and exit; behavior
could be modifiable at run time so that tracer can go away into oblivion.

Given the current semantics of create, this wouldn't work. What would be
reasonable syntax and semantics to make something like this possible?

Maybe this would need to be a separate PEP. But it seems at least
somewhat related.

I think this probably needs a separate PEP. Function definitions are
really very different from class definitions. But feel free to write
that PEP. ;)

STeVe
 
S

Sion Arrowsmith

Kay Schluehr said:
Have you a rough estimation how many modules will be broken when
"create" is introduced as a keyword?

A quick scan of the standard library suggests that it will have
a grand total of 3 modules requiring a fix (it's a method name
in imaplib and a named argument in a couple of places in bsddb
and distutils). Your own code my fare worse (mine does, but not
by much).
 
M

Michael Ekstrand

Steven said:
I think this probably needs a separate PEP. Function definitions are
really very different from class definitions. But feel free to write
that PEP. ;)

If I have extra time this summer, maybe. It'd be fun to write a PEP and
figure out how to add it in to Python. But that will definitely have to
wait until *after* semester tests, if I can even get to it at all...

- Michael
 
A

Azolex

M

Michele Simionato

Sion said:
A quick scan of the standard library suggests that it will have
a grand total of 3 modules requiring a fix (it's a method name
in imaplib and a named argument in a couple of places in bsddb
and distutils). Your own code my fare worse (mine does, but not
by much).

This agrees with my scan (except I also found an occurrence of 'create'
in Tkinter).
BTW, I would be curious to see the script you are using for the
scanning. Are you
using tokenize too? In am quite fond of the tokenize module ;)

Michele Simionato
 
R

Ron Adam

Abstract
========

This PEP proposes a generalization of the class-declaration syntax,
the ``create`` statement. The proposed syntax and semantics parallel
the syntax for class definition, and so::

create <callable> <name> <tuple>:
<block>

is translated into the assignment::

<name> = <callable>("<name>", <tuple>, <namespace>)

where ``<namespace>`` is the dict created by executing ``<block>``.
The PEP is based on a suggestion [1]_ from Michele Simionato on the
python-dev list.


I'll have to think on this one a bit. So I'm undecided for now.


Could it possibly use the 'as' keyword?

create <callable> <tuple> as <name>:
<block>



It has also been suggested that a pattern where functions and classes
are assigned be used. Possibly something like...

name = class():
<block>

name = def():
<block>

name = create():
<block>


Or it could be...

name = object():
<block>


This is a bigger change than adding the create keyword, (definitely not
a pre-P3k item), and I'm not sure if it fits your use case, but it does
allow for a larger variety of types without adding additional keywords.

Cheers,
Ron
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,698
Latest member
LydiaHalle

Latest Threads

Top