Implicit conversion to boolean in if and while statements

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Feb 8 16:16:42 CET 2013


Rick Johnson wrote:

> GvR has always been reluctant to incorporate full OOP machinery for some
> reason.

Python is a fully object oriented language. It is *more* object oriented
than, say, Java.

- everything in Python is an object, there is no distinction between "boxed"
and "unboxed" variables;

- modules are objects;

- functions and methods are objects;

- classes are objects in Python, and have their own class (the metaclass);

- metaclasses themselves are also objects, and have classes of their own;

- it's objects all the way down, at least until you reach "type" itself,
which is bootstrapped into existence by the compiler.


Although Python is fully object-oriented, it does not insist on one
particular style of object syntax. It allows procedural and functional
style syntax as well.


> I am not suggesting that Python be 100% OOP, HELL NO! But 
> collections should have had an "isempty" method from the beginning. But
> the same argument could be made against len, any, all, etc...

No they shouldn't.

http://effbot.org/pyfaq/why-does-python-use-methods-for-some-functionality-e-g-list-index-but-functions-for-other-e-g-len-list.htm

http://lucumr.pocoo.org/2011/7/9/python-and-pola/

http://mail.python.org/pipermail/python-dev/2008-January/076612.html


Python functions operate as *protocols*. any() and all(), for example, are
excellent examples of why your suggestion fails: the principle of "Don't
Repeat Yourself".

In Python today, any() and all() will work perfectly on ANY ITERABLE OBJECT,
for free. The developer of that object doesn't need to do anything to
support any() and all(), all she has to do is make it iterable.

Under your suggestion, every iterable object has to implement an any()
method, and an all() method. Every iterable type has to repeat the same old
code as every other iterable type. 

class list:
    def any(self):
        for x in self:
            if x: return True
        return False

class dict:
    def any(self):
        for x in self:
            if x: return True
        return False

class set:
    def any(self):
        for x in self:
            if x: return True
        return False

class MyFancyIterableThatIsRealCool:
    # Wow, deja vu... 
    def any(self):
        for x in self:
            if x: return True
        return False


See all the pointlessly duplicated code? Now each one needs tests, and
documentation, and the amount of duplication goes through the roof.

Now, a developer of merely average intelligence will see all that duplicated
code, and factor it out into a global function (two actually, one for
any(), one for all()):

def any(iterable):
    # Write this once. Test it once. Document it once.
    for x in iterable:
        if x: return True
    return False

class list:
    # Gotta have a method, or Rick will cry.
    def any(self):
        return any(self)

class dict:
    def any(self):
        return any(self)

class set:
    def any(self):
        return any(self)

class MyFancyIterableThatIsRealCool:
    # This code seems trivial, and familiar... 
    def any(self):
        return any(self)


But a developer of above average intelligence will recognise that all those
x.any() boilerplate methods are *pointless and stupid*, since you have a
function that does everything you need, for every possible iterator, for
free. All you need do is use any(obj) syntax instead of obj.any() syntax,
which also saves one keystroke.

And a *really* smart language designer will have realised this ahead of
time, and designed the language to encourage the use of protocols like
this, instead of insisting on the slavish application of obj.method syntax.




-- 
Steven




More information about the Python-list mailing list