PEP 318 : Def and Class in expressions

PF peufeu at free.fr
Sat Mar 27 13:46:50 EST 2004


	Hello,

	I'm pleased to see activity on this topic as it pains me to write 
"classmethod" two pages of code after the method definition. However I 
find the decorators to obfuscate the syntax and lessen the expressivity 
(ie. they restrain what can be done).

	All these problems come from the fact that the execution of the 
"foo=staticmethod(foo)" must be delayed after the execution of the "def" 
statement because it must act on the function after it has been defined.

	Normal program execution thus flow forces it to be placed after the 
"def", while readability would require it to be placed *before* the 'def'.

	How to reverse the execution order ? One method would be to use an 
expression, but that would get very ugly soon, and Python's indented 
syntax does not lend itself well to such twistings. To mix a few previous 
postings :

	mymethod = staticmethod( def (args):
		method code...
		)

	is just plain ugly.

	mymethod = staticmethod( def (args) ):
		method code...

	is also quite ugly.

	I don't like the decorators either.

	So the root of the problem is the fact that the source code executes from 
top to bottom. I see two solutions.
	1. Use a text editor which can fold functions, hiding the code between 
the def and the staticmethod call
	2. Reverse the flow of code.

	Ha.
	I'm gonna propose a flame bait, read on. It's about code blocks.

	Say we introduce a new keyword : 'block'. Here is the syntax :

	block (block-class,block-name):
		some code
		some code
		some code

	A block of code is thus an object, deriving from a base class (say, 
'CodeBlock'). It can have children too (other blocks of code), which can 
have names.
	If omitted, block-class defaults to CodeBlock, and block-name to None.
	(block-class,block-name) is a tuple, so the following are equivalent :

	block-class			=> (block-class,None)
	block-class,block-name	=> (block-class,block-name)
	(,block-name)		=> (CodeBlock,block-name)

	Example in the classmethod thingie :

	block InvertingCodeBlock:
		block:
			mymethod = staticmethod(mymethod):
		block:
			def mymethod(arg1, arg2):
				some code

	where InvertingCodeBlock: is a block class which executes its children in 
inverted order. This object has two children, both of class CodeBlock.

	I invented the syntax as it came, it sucks, but it's just so you get the 
idea. Feel free to propose something better. But first look at the 
following.

	Now, this has other, more interesting, things into it.
	Example :

def crapthread( params ):
	acquire_lock( global_lock )
	do something
	release_lock( global_lock )

	This example sucks because any exception happening in "do something" will 
not release the lock, and the lock must be manually released before every 
return.

	Now, CodeBlock can have children. What if CodeBlock decides the children 
could be executed in a certain order ?
	For instance, we could have children names "init", "run", "cleanup" which 
would run in this order.
	We could then write :
	
def crapthread( params ):
	block:
		block (,'init'):
			acquire_lock( global_lock )
		block (,'run'):
			do something
		block (,'cleanup'):
			release_lock( global_lock )

	I expect anyone will understand how this works. The parent block would 
execute 'init', then 'run', then 'cleanup', then pass anu return'ed value 
or exceptions.

	If the 'def' statement implies creation of a code block, we could omit 
the first 'block:'

	The classmethod example cound be rewritten as :
	block:
		block (,'init'):
			mymethod = staticmethod(mymethod):
		block (,'run'):
			def mymethod(arg1, arg2):
				some code

	We could define other types of children too, like a version of cleanup 
which is executed oly when no exceptions occur in "run".

	Now let's add the __currentblock__ which gives us a reference to the 
block we're in, and give the block object a way to add children of a 
certain type. We could thus register cleanup actions to be executed at the 
end of a function when needed.

	try-except-finally could also be done with blocks.

	All this is very preliminary thinking. I hope it fuels your inspiration. 
I feel this could be powerful, and also pythonic. What do you think ?

	Thanks for your time,

	Pierre



More information about the Python-list mailing list