Dear Python Developers,
We have a potential idea for enhancing Python. You will find a kind of draft bellow.
Best regards,
Daniel Bershatsky
Abstract
========
This PEP proposes the introduction of new syntax to create community standard,
readable and clear way to defered function execution in basic block on all
control flows.
Proposal
========
There is not any mechanism to defer the execution of function in python. In
order to mimic defer statement one could use either try/except construction or
use context manager in with statement.
We suggest to introduce defer statement to defer the execution of functions
until function returns.
```python
def foo(i):
print(i)
def bar():
defer foo(42)
print(3.14)
bar()
```
In code bellow execution result was
```
3.14
42
```
The reason is function foo is marked with defer keyword and it is not called
immediatly. In fact Python VM invokes print function before foo function which
is called on returning from bar function. Important to note that argument of
foo function must be evaludated on defer statent appered.
```python
def foo(i):
print(i)
def bar():
defer foo(42)
if True:
print(2.18)
return
print(3.14)
bar()
```
Since defer statement is executed after function returns, output is
```
2.18
42
```
Another side of defer statement is order of invokation of defered functions.
In example bellow baz function contains defer calls of foo and bar
corespondently but order of actual invokation is reversed. On returning from
baz function bar function is called first and then bar function.
```python
def foo():
print(1)
def bar():
print(2)
def baz():
defer foo()
defer bar()
baz()
```
The output is
```
2
1
```
Rationale
=========
There are two the most common examples of usefull usage of defer calls based
on source code of Python 3.5.2 standard lib.
multiprocessing/queues.py:101-111 part of Queue.get()
```python
try:
if block:
timeout = deadline - time.time()
if timeout < 0 or not self._poll(timeout):
raise Empty
elif not self._poll():
raise Empty
res = self._recv_bytes()
self._sem.release()
finally:
self._rlock.release()
```
In this piece of code try/finally is used only to release lock in any
execution branches dispite of raise exeption. By introducing defer statement
we can ensure that the lock are always released, remove extra intendation and
make code block more straight.
urllib/request.py:1732-1771 part of URLopener.retrive()
```python
fp = self.open(url, data)
try:
headers = fp.info()
if filename:
tfp = open(filename, 'wb')
else:
import tempfile
garbage, path = splittype(url)
garbage, path = splithost(path or "")
path, garbage = splitquery(path or "")
path, garbage = splitattr(path or "")
suffix = os.path.splitext(path)[1]
(fd, filename) = tempfile.mkstemp(suffix)
self.__tempfiles.append(filename)
tfp = os.fdopen(fd, 'wb')
try:
result = filename, headers
if self.tempcache is not None:
self.tempcache[url] = result
bs = 1024*8
size = -1
read = 0
blocknum = 0
if "content-length" in headers:
size = int(headers["Content-Length"])
if reporthook:
reporthook(blocknum, bs, size)
while 1:
block = fp.read(bs)
if not block:
break
read += len(block)
tfp.write(block)
blocknum += 1
if reporthook:
reporthook(blocknum, bs, size)
finally:
tfp.close()
finally:
fp.close()
```
This is the most awkward argument in favor of defer keyword. Nested
try/finally blocks can be easily replaced with only two lines of code
```python
defer fp.close()
defer tfp.close()
```
Also there is more synthetic pattern that replace with statement. For example,
```bash
with open(filename) as fin:
# some stuff
```
Or with usage defer keyword
```
fin = open(filename)
defer fin.close()
# some stuff
```
Implementation
==============
Introduction defer statement requires modifying gramar file to parse for new
keyword. Also changes to Python.asdl, ast.c, compile.c is needed. Probably to
adopt defer statement one should modify callable implementation.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/