Implicit conversion to boolean in if and while statements

Rick Johnson rantingrickjohnson at
Fri Feb 8 18:48:43 CET 2013

On Friday, February 8, 2013 9:16:42 AM UTC-6, Steven D'Aprano wrote:
> 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.

Oh really? *chuckles*

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

Just because /everything/ in Python is an object does not mean that Python is 100% OOP. This fact is just one of the many attributes of a 100% OOP language. Yes, Python allows OOP style, but python is NOT 100% OOP! Ruby on the other hand /is/ 100% OOP. Although it has identity issues like Python. Ruby thinks it's multi-paridigm and Python thinks it's a good example of OOP. Neither are correct.

> - 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.

Well you just defeated yourself. How can Python be 100% OOP and then allow other paradigms? 

> > 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.
> [...]
> 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.


If so, Python would have a supertype called "Collection" that wold define all methods that operate on collections. Some of these include:

 len, any, all, length, isempty, __getitem__, __setitem__, etc...
Then any collection subtype would inherit from this supertype and get the methods for free.

> [...]
> 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()):

Only if that developer does not understand sub-typing! All he has to do is write the method ONE TIME in a super-type, and then inherit the method into ANY number of sub-types for free. Now, if he wants to pervert the usage of a method to fit some niche, THEN he will need to overload the method and provide proper return value.

> 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.

Using built-in functions to operate on objects is foolish because you are placing extra burden on the programmer to know which /functions/ work with which /types/. The *only* functions that should be global are the kind that will work on *ANY* object. But then again, the Object type could hold these methods!

len, all, and any (just to name a few) only work for collections types and as such should be methods of these types. The global functions:
  sum, len, any, all, enumerate, map, max, min, reversed, sorted, zip
can only be applied to sequence types, or subtypes of a sequence type. So using a /real/ OOP paridigm we would do the following:


class Object(SuperType):
    def __class__
    def __delattr__
    def __doc__
    def __format__
    def __getattribute__
    def __init__
    def __new__
    def __repr__
    def __setattr__
    def __sizeof__
    def __str__
    def __subclasshook__
    def true? # aka: bool
    def callable?
    def compare(other)
    def dir
    def hash
    def help
    def id
    def isinstance?(Type)
    def issubclass?(Type)
    def super
    def type

class SequenceBase(Object):
    # Methods from object are free
    def __add__
    def __contains__
    def __delattr__
    def __delitem__
    def __delslice__
    def __eq__
    def __ge__
    def __getitem__
    def __getslice__
    def __gt__
    def __iadd__
    def __imul__
    def __iter__
    def __le__
    def __lt__
    def __mul__
    def __ne__
    def __reduce_ex__
    def __rmul__
    def __setitem__
    def __setslice__
    def __subclasshook__
    # Interface
    def iterator
    def length
    def sum
    def any
    def all
    def enumerate
    def filter(proc)
    def frozenset
    def map
    def max
    def min
    def reverse
    def reduce(proc)
    def slice
    def sort
    def zip

class MySequencyThing(SequenceBase):
    # do something here

class List(SequenceBase):
    # Methods from SequenceBase and Object are free!
    # Interface
    def append
    def count
    def extend
    def index
    def insert
    def pop
    def remove
    def reverse
    def sort

class MyListyThing(List):
    # do something here


You see, 100% OOP uses encapsulation, inheritance, sub-typing, etc, etc... But most fundamental to OOP is interface (methods belonging to objects), not global functions applied to objects in some haphazard fashion that some self-appointed dictator pull from his backside due to his fear of true OOP style!

Python is not 100% OOP. Heck you cannot fairly apply a specific percentage level because Python's level of OOP is defined by each user of the language. The best way to describe Python is as promiscuous language who secretly longs to be 100% OOP, and to fulfill this fantasy it cross-dresses in OOP lingerie on the weekends.

More information about the Python-list mailing list