python 3's adoption

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Thu Jan 28 19:00:57 EST 2010


On Thu, 28 Jan 2010 18:37:56 +0100, Alf P. Steinbach wrote:

> * Lie Ryan:
>> On 01/28/10 20:12, Alf P. Steinbach wrote:
>>>   >>> import builtins
>>>   >>>
>>>   >>> org_print = print
>>>   >>> builtins.print = 666
>>>   >>>
>>>   >>> print( "trallala" )
>>>   Traceback (most recent call last):
>>>     File "<stdin>", line 1, in <module>
>>>   TypeError: 'int' object is not callable
>>>   >>> org_print( "but is that really so smart?" )
>>>   but is that really so smart?
>>>   >>> _
>> 
>> Monkey patching follows (or should follow) the same rule as class
>> inheritance overriding: the overrider's input domain must be a superset
>> of the overriden's input domain and the overrider's output range must
>> be a subset of the overriden's output range. 666 object (int) is not
>> even remotely compatible with function object.
> 
> Yes, that's my point.
> 
> A 'print' replacement should ideally provide all the guarantees on
> behavior that standard 'print' does.
> 
> And with that it's not so easy to put in a /correct/ replacement of
> 'print'; in particular, it has to honor the 'file' keyword argument.

Oh come on, that's easy. This is Python we're talking about. Any object 
with a write() method is valid.


>>> class MyIO:
...     def __init__(self):
...             self.buffer = []
...     def write(self, *args):
...             self.buffer.extend(args)
...
>>> io = MyIO()
>>> print("Say goodnight Gracie", "Goodnight Gracie!", file=io)
>>> io.buffer
['Say goodnight Gracie', ' ', 'Goodnight Gracie!', '\n']


In many cases, probably most, you won't be writing your own full-blown 
print replacement, but merely decorating the existing function. How easy 
is that? Trivial. Here's how to shut down a noisy module that prints too 
much:

>>> def make_quieter(func):
...     def inner(*args, **kwargs):
...             out = kwargs.get('file')
...             if out in (None, sys.stdout):
...                     pass
...             else:
...                     func(*args, **kwargs)
...     return inner
...
>>> print = make_quieter(print)
>>> print("spam spam spam")
>>> print("spam spam spam", file=io)
>>> io.buffer
['Say goodnight Gracie', ' ', 'Goodnight Gracie!', '\n', 'spam spam 
spam', '\n']

(except of course you would monkey-patch the module).

Because print is a built-in, getting the original version back is even 
easier:

>>> del print
>>> print("spam spam spam")
'spam spam spam'


 
> Thus the 3.x design makes it easy to replace 'print' incorrectly.

This is Python -- the compiler won't stop you from shooting yourself in 
the foot.

>>> len = 666
>>> len("hello world")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable


> I'd rather still had 'print' as keyword... ;-)

We've shown many benefits of print as a function. Can you give any 
benefits of it being a statement, other than backward compatibility for 
those who learned it from Python 2.x?

If you were designing your own language from scratch, so that backwards 
compatibility wasn't an issue, why would you make print a statement?



-- 
Steven



More information about the Python-list mailing list