python without OO

J

John Hunter

Davor> not really - it was not my intention at all - but it seems
Davor> people get upset whenever this OO stuff is mentioned - and
Davor> what I did not expect at all at this forum as I believed
Davor> Python people should not be so OO hardcore (seems not all
Davor> as quite a few have indicated in their
Davor> replies)... Nevertheless, I think the discussion has
Davor> several quite good points! --
Davor> http://mail.python.org/mailman/listinfo/python-list

Consider the case of a list, say

x = [1,2,3,4]

suppose you wanted to reverse the list, so that x becomes [4,3,2,1].
In a procedural language, one might do

x = reverse(x)

In an OO language such as python, one might do

x.reverse()

Is the OO way more obscure and complicated, etc? Not really -- it's
only a minor syntactical difference. One of the core ideas behind OO
programming is that data (the contents of the list 1,2,3,4) and
methods (sorting, reversing) are bound together into a single entity,
the object. On the face of it, this is rather sensible.

You may rightly recoil against unnecessary abstraction and complexity,
abuse of multiple inheritance and so on. That's perfectly sensible.
But object orientation is probably not the bogey man here. python
values readable code that is as simple as possible (but no simpler!)
as you seem to. Focus on the actual problem, which is probably not OO
programming, but colleagues who are making a design more complex than
need be.

Indeed, the third chant in the mantra of python is "Simple is better
than complex."

John-Hunters-Computer:~> python
Python 2.3 (#1, Sep 13 2003, 00:49:11)
[GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin
Type "help", "copyright", "credits" or "license" for more information.The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
 
D

Davor

I'd like to thank everyone for their replies. The main important lesson
I got is:

Python does not have that many issues with misuse of OO as compared to
Java/C++ because it's *dynamically* typed language and extremely
powerful *dictionary* data structure.

I browsed docs a bit today, and they also confirm what I have believed -
that OO is totally secondary in Python. In fact,
object/classes/metaclasses are nothing but *dictionaries with identity*
in python. Love this approach. In fact, you can very easily implement
your own *OO model* completely separate of Python's OO model... Now I
actually strongly believe that Python's author has introduced the whole
OO model just to attract and make happy OO population... In fact,

*Python's dynamic type checking mechanisms + dictionary is way more
powerful than Java/C++'s static type checking mechanisms + their OO
mechanisms*

and you can definitely be more productive using Python's structured
programming than Java/C++ OO programming :)... and Python is probably
the best example why we should have skipped OO all together..

---
second, instead of playing with OO plagued design principles do as follows:

1. separate data, functionality, and structure from each other as much
as you can (in Python only valid structural element I've seen so far is
module - ignore objects & classes!)
2. do not assume any have identity (even if the underlying language
model provides and uses one) - so don't pass them around and crazy stuff...

so you get a nice program with separate data structures and functions
that operate on these data structures, with modules as containers for
both (again ideally separated). Very simple to do and maintain no matter
what OO preachers tell you...

Davor
 
B

beliavsky

John said:
Davor> not really - it was not my intention at all - but it seems
Davor> people get upset whenever this OO stuff is mentioned - and
Davor> what I did not expect at all at this forum as I believed
Davor> Python people should not be so OO hardcore (seems not all
Davor> as quite a few have indicated in their
Davor> replies)... Nevertheless, I think the discussion has
Davor> several quite good points! --
Davor> http://mail.python.org/mailman/listinfo/python-list

Consider the case of a list, say

x = [1,2,3,4]

suppose you wanted to reverse the list, so that x becomes [4,3,2,1].
In a procedural language, one might do

x = reverse(x)

In an OO language such as python, one might do

x.reverse()

Is the OO way more obscure and complicated, etc? Not really -- it's
only a minor syntactical difference. One of the core ideas behind OO
programming is that data (the contents of the list 1,2,3,4) and
methods (sorting, reversing) are bound together into a single entity,
the object. On the face of it, this is rather sensible.

I think the OO way is slightly more obscure. It's obvious what x =
reverse(x) does, but it is not clear unless you have the source code
whether x.reverse() reverses x or if it returns a reversed list. If
x.reverse() does the former, a disadvantage relative to the procedural
approach is that a function can be used in an expression. It is clearer
and more concise to write

z = reverse(x) + reverse(y)

than

x.reverse()
y.reverse()
z = x + y

Furthermore, if in Python the algorithm for the reverse function
applies to many kinds of objects, it just needs to be coded once,
whereas a reverse method would have to provided for each class that
uses it (perhaps through inheritance).
 
C

Casey Hawthorne

"The object-oriented programming paradigm has an undeserved reputation
as being complicated; most of the complexity of languages such as C++
and Java has nothing to do with their object orientation but comes
instead from the type declarations and the mechanisms to work around
them. This is a prime example of how Scheme's approach of removing
restrictions compares with the "piling feature on top of feature"
needed in other languages, such as the C++ template mechanism."

"Handbook of Programming Languages, Volume IV: Functional and Logic
Programming Languages"
Peter H. Salus, editor
1998
page 63

Similarly, now, Java's generics!
 
J

John Hunter

beliavsky> I think the OO way is slightly more obscure. It's
beliavsky> obvious what x = reverse(x) does, but it is not clear
beliavsky> unless you have the source code whether x.reverse()

You don't need to read the src, you just need to read the docs
Help on built-in function reverse:

reverse(...)
L.reverse() -- reverse *IN PLACE*

beliavsky> reverses x or if it returns a reversed list. If
beliavsky> x.reverse() does the former, a disadvantage relative to
beliavsky> the procedural approach is that a function can be used
beliavsky> in an expression. It is clearer and more concise to
beliavsky> write

beliavsky> z = reverse(x) + reverse(y)

The distinction is not OO versus procedural, it is a decision about
how you choose to write "reverse". The python list implementers of
the reverse object method could have decided to return a new reversed
list rather than do the reverse in place and return None. Then you
could have done

z = x.reverse() + y.reverse()

They could have chosen to reverse the list *in place* and also
returned a reference to self rather than None, in which case you could
do the above as well. w/o digging up the transcripts from the
python-dev mailing list, my guess is that they choose to do it in
place for efficiency in memory and cpu, and chose not to return self
to prevent user confusion. Ie, if a user was allowed to do 'z =
x.reverse() + y.reverse()' they might be surprised to find the side
effect of in place modification.

Likewise, I could easily write a procedural "in place" reverse that
returns None, in which case 'z = reverse(x) + reverse(y)' would not do
what you suggest. My point is that whether a function/method such as
reverse operates in place or on a copy, and whether it returns None or
a reference to a list is independent of OO vs procedural style and is
motivated by considerations of efficiency, readability, and usability.

beliavsky> Furthermore, if in Python the algorithm for the reverse
beliavsky> function applies to many kinds of objects, it just
beliavsky> needs to be coded once, whereas a reverse method would
beliavsky> have to provided for each class that uses it (perhaps
beliavsky> through inheritance).

True, a generic reverse procedure/function can be applied to any data
structure that supports iteration. In the case of python, however,
some iterable data structures are mutable (lists, dicts) and some are
not (strings, tuples). For mutable sequences, an in place reverse is
likely to be more efficient in memory and perhaps CPU than a generic
reverse which returns a new copy. So a specialized method "reverse"
applicable to lists (but not strings and tuples) can be a big win.
Fortunately, python supports both, allowing you to define a general
"reverse" that works for any object that supports the sequence
protocol, as well as to define an object specific reverse method that
may be faster in time and space.

JDH
 
I

Isaac To

beliavsky> I think the OO way is slightly more obscure. It's
beliavsky> obvious what x = reverse(x) does, but it is not clear
beliavsky> unless you have the source code whether x.reverse()
beliavsky> reverses x or if it returns a reversed list.

What make it so clear to you that reverse(x) will always return a
reversed list rather than reversing x in place and return nothing?

beliavsky> It is clearer and more concise to write
beliavsky> z = reverse(x) + reverse(y)
beliavsky> than
beliavsky> x.reverse()
beliavsky> y.reverse()
beliavsky> z = x + y

This isn't anything to do with OO programming. It is something about
using in interface that your audience expects. You have exactly the
same problem whether you are using procedural or OO style. It might
be a case for functional programming, but that's something off-topic.

beliavsky> Furthermore, if in Python the algorithm for the reverse
beliavsky> function applies to many kinds of objects, it just
beliavsky> needs to be coded once, whereas a reverse method would
beliavsky> have to provided for each class that uses it (perhaps
beliavsky> through inheritance).

That the reverse() wants to be a function doesn't mean that the thing
that reverse() operate on doesn't want to be an object. So this isn't
very clear a problem about OO style vs. procedural style, but instead
a problem about "generic" programming style vs. "concrete" programming
style. On the other hand, if the thing that reverse() operate on
isn't an object sharing the same interface, it will be more clumsy to
implement a generic reverse() that works for all the different kinds
of object---even if they share similar interfaces. Try to implement a
generic "reverse" in C when the different type of containers are
encoded as different style struct's accessible from different
function, and you will understand what I mean. So this is,
marginally, a case *for* OO style.

Regards,
Isaac.
 
C

Craig Ringer

I browsed docs a bit today, and they also confirm what I have believed -
that OO is totally secondary in Python. In fact,
object/classes/metaclasses are nothing but *dictionaries with identity*
in python. Love this approach.

I was really impressed with the design of the language, especially this
bit. I first "got" it when reading Learning Python 2nd Ed (well *after*
I'd been using Python for a while, but it's always good to read even
intro books to fill out "obvious" things you might've missed). I love
the way the same "It's just a dictionary search" principle applies to
inheritance, scoped variable lookups, etc.

In Python, even metaclasses just operate on the class dictionary. How
pleasantly simple :) - especially how the step from class factory to
metaclass is so small and approachable.

I also love the way I can chuck a bunch of objects into a functionally
styled processing pipeline, say a series of functions that each just
return the result of a listcomp/genexp.
 
M

michele.simionato

Davor said:
Thanks,

I do not hate OO - I just do not need it for the project size I'm
dealing with - and the project will eventually become open-source and
have additional developers - so I would prefer that we all stick to
"simple procedural" stuff rather than having to deal with a developer
that will be convincing me that his 50 layers inheritance hierarchy is
good since it exists in some weird pattern that he saw somewhere on
some Java design patterns discussion board :) and other "proper" OO
design issues... Once I opted for C++ in a very small project and
believed everyone will stick with C subset + better type checking
offered through C++ - but I simply could not manage to keep them off
using OO stuff which was just making program more complicated than it
should have been. (note, I am not an experienced developer, nor the
others I'll be working with (even though some think they are:)), so I
prefer preemptively dealing with issue of everyone showing off their OO
design skills)

I think Davor is making an important point here: Python has grown in
the last 14 years, and it is no more the simple scripting language
it used to be. In particular, it evolved a lot of OOP "cruft"
(static/classmethods, properties, the __new__ method, super, the new
MRO, descriptors,metaclasses, etc.) and there is more than a learning
curve issue coming with the added complexity. Davor is right: even if
you do not want to use it, the stuff is *there* and somebody in your
team will. So definitely there is an audience of programmers that just
do not have an use for all the sophistication and actually are
penalized by it.

There is not much than can be done at the Python level. But I would
see with interest a Python spinoff geared towards simplicity. Few
months ago there was the Prothon proposal (by all means a terrible
proposal) but the goal that motivated it (simplification, trying
to remove classes) was in my opinion worthwhile.

Now, *how* to remove (or simplify) classes is not at all clear to me,
not I am convinced that prototypes are the right way to go, but still I
feel that there is something wrong with inheritance. Maybe
protocols are the solution, who knows? But in any case I think it
is important to keep searching for semplicity. I do not believe
Python is the definitive language, and it is probabily possible
to introduce something better. It is just that nothing of the
kind appeared until now, but I keep watching at the horizon ;)
Michele Simionato
 
T

Timo Virkkala

Davor said:
not really - it was not my intention at all - but it seems people get
upset whenever this OO stuff is mentioned - and what I did not expect at
all at this forum as I believed Python people should not be so OO
hardcore (seems not all as quite a few have indicated in their
replies)... Nevertheless, I think the discussion has several quite good
points!

Yes, sorry about that. I posted too soon. After posting I read more of your
posts and realized that you really mean it, so I tried to cancel my message, but
apparently it got through (news message canceling has never been that reliable..).

I believe that if you take the time to do some Python programming, you can find
out that OO, when used correctly, is not the huge monster your previous
languages had led you to believe it is. In Python, you can use just the right
amount of OO to make things easier and more sensible, without complicating
things with huge inheritance trees and unnecessary polymorphism.

Again, sorry about my premature judgement.
 
T

Timo Virkkala

I think the OO way is slightly more obscure. It's obvious what x =
reverse(x) does, but it is not clear unless you have the source code
whether x.reverse() reverses x or if it returns a reversed list. If
x.reverse() does the former, a disadvantage relative to the procedural
approach is that a function can be used in an expression. It is clearer
and more concise to write

Sure, it's clear if in written code you see

x = reverse(x)

To me it would also be clear to see

x.reverse()

But what if you just see in some list that there is a reverse(sequence)
function, or that a sequence has a reverse() method? To me, neither of these is
clear. Do they return a new, reversed sequence or reverse in place?

When creating a new API, I would probably use a convention where reverse does it
in place and reversed returns a new. So, in my API,

reverse(x)
y = reversed(x)
x.reverse()
y = x.reversed()
 
P

Peter Maas

Terry said:
But if the class method syntax were
manditory, there would be class and/or class hierarchy bloat due to the
unlimited number of possible functions-of-a-float and large number of
actual such functions that have been written.

You are right. I'm not an OO purist, I just wanted to convince Davor,
that anti-OO purism can be harmful too. It's good for programmers to
have a choice.
Your Four Steps to Python Object Oriented Programming - vars, lists, dicts,
and finally classes is great.

I'm glad you like it :)
 
P

Peter Maas

Davor said:
I browsed docs a bit today, and they also confirm what I have believed -
that OO is totally secondary in Python.

OO is not secondary in Python. It's secondary for you :) And Python
leaves the choice to you.
In fact,
object/classes/metaclasses are nothing but *dictionaries with identity*
in python.

Eliminating "nothing but" makes this a true statement :)

Love this approach. In fact, you can very easily implement
your own *OO model* completely separate of Python's OO model... Now I
actually strongly believe that Python's author has introduced the whole
OO model just to attract and make happy OO population...

I believe that your belief is wrong :) Guido van Rossum has introduced
OO to Python because it's a useful concept.
and you can definitely be more productive using Python's structured
programming than Java/C++ OO programming :)... and Python is probably
the best example why we should have skipped OO all together..

Sigh. Proceed as you like but be aware that dogmatism - OO as well as
anti-OO is always a poor guide. OO wasn't invented as a marketing buzz
but to support programming styles that emerged in non-OO languages to
control the increasing complexity of programs.
so you get a nice program with separate data structures and functions
that operate on these data structures, with modules as containers for
both (again ideally separated). Very simple to do and maintain no matter
what OO preachers tell you...

The bad thing about OO preachers is not OO but preaching. And you
are preaching, too ;)
 
N

Nick Coghlan

Furthermore, if in Python the algorithm for the reverse function
applies to many kinds of objects, it just needs to be coded once,
whereas a reverse method would have to provided for each class that
uses it (perhaps through inheritance).

Indeed, this is why Python not only provides the list.reverse() method to
reverse a list in place, but also provides the reversed() function to reverse
any sequence:

Py> lst = list("ABCDEFGHIJ")
Py> lst.reverse()
Py> print "".join(lst)
JIHGFEDCBA
Py> print "".join(reversed(lst))
ABCDEFGHIJ

Ditto list.sort() and sorted().

Cheers,
Nick.
 
N

Nick Coghlan

Then why was C++ invented? What you have described can be done in C,
Pascal, and Fortran 90, all of which are generally classified as
procedural programming languages. As Lutz and Ascher say in "Learning
Python", in object-based programming one can pass objects around, use
them in expressions, and call their methods. "To qualify as being truly
object-oriented (OO), though, objects need to also participate in
something called an inheritance hierarchy."

Again, behavioural inheritiance is something which can be done manually via
delegation or function tables.

What a language with OO support adds is special syntax for something that you
could have done anyway - the OO support just makes it easier and clearer (well,
C++ aside).

Cheers,
Nick.
 
P

Peter Maas

Davor is right: even if
you do not want to use it, the stuff is *there* and somebody in your
team will. So definitely there is an audience of programmers that just
do not have an use for all the sophistication and actually are
penalized by it.

No, because Python does not enforce using advanced concepts. You
can write programs that are as simple as in 1991. A group of developers
always has to find some kind of common style with a chance that some
are penalized. This can happen with every language.
There is not much than can be done at the Python level. But I would
see with interest a Python spinoff geared towards simplicity.

I think this would be useless because advanced concepts exist for
a reason. A simplified spin-off would aquire advanced concepts
over time and would just become a clone of Python.
 
N

Nick Coghlan

Davor said:
data structures
> and
> functions that operate on these data structures

Eh? What do you think a class is?

Py> data = range(10)
Py> list.extend(data, range(5))
Py> list.sort(data)
Py> print data
[0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9]

The fact that data.extend(range(5)) and data.sort() are alternative spellings
for the second and third lines doesn't change the fact that a class is just a
data structure grouped with a bunch of functions that operate on that data
structure.

Cheers,
Nick.
 
M

michele.simionato

Peter Maas:
(e-mail address removed) schrieb:
No, because Python does not enforce using advanced concepts. You
can write programs that are as simple as in 1991. A group of developers
always has to find some kind of common style with a chance that some
are penalized. This can happen with every language.

No. In theory C++ could be kept as simple as C but in practice it is
not.
I think this would be useless because advanced concepts exist for
a reason. A simplified spin-off would aquire advanced concepts
over time and would just become a clone of Python.

And then we will need another simplified spinoff ;)
There is always a fight between simplificity and complexity.
Some complexity is not needed, and I am sure even in Python
something could be dropped. But it is difficult to find what can
be removed. Remember that Saint-Exupery quote? Something
like "a work of art is finished when there is nothing left to remove?"
M.S.
 
A

Alex Martelli

Some complexity is not needed, and I am sure even in Python
something could be dropped. But it is difficult to find what can
be removed. Remember that Saint-Exupery quote? Something
like "a work of art is finished when there is nothing left to remove?"

Saint-Éxupery was an engineer (and a pioneer of flight) and so he was
referring to a designer (and no doubt had in mind those planes...), not
to an artist (not his fault if he's better remembered as a novelist;-).

As for what can be removed from Python, one could start at
<http://www.python.org/peps/pep-3000.html> -- while each of us will find
there some "complexity" one loves and uses often (be it lambda, buffer,
reload, ...), it's a good start.


Alex
 
A

Alex Martelli

PA said:
Yes. But even with the "best" tool and the "best" intents, projects
still fail. In fact, most IT projects are considered failures:

http://www.economist.com/business/PrinterFriendly.cfm?Story_ID=3423238

The main thesis of the article you quote (although it acknowledges that
other think differently) is that better tools (including iterative, NOT
waterfall, development; and, agile programming approaches, more
generally) are the way to mitigate that horrid track record.


Alex
 
B

beliavsky

And then we will need another simplified spinoff ;)
There is always a fight between simplificity and complexity.
Some complexity is not needed, and I am sure even in Python
something could be dropped. But it is difficult to find what can
be removed. Remember that Saint-Exupery quote? Something
like "a work of art is finished when there is nothing left to remove?"
M.S.

"Perfection is achieved, not when there is nothing more to add, but
when there is nothing left to take away."

I know this quote because it is the motto of the F programming language
http://www.fortran.com/F/ , a "simplified spinoff" of Fortran 95.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,151
Latest member
JaclynMarl
Top