Does Python really follow its philosophy of "Readability counts"?

P

Paul Rubin

Bruno Desthuilliers said:
Already possible - you just have to provide your own implementation of
__setattr__.

Part of the idea of non-dynamic attribute sets is to make the program
run faster, not slower.
 
M

Mel

Russ said:
Yes, that would indeed be nice. I am certainly not the only one who
could use a language that is excellent for both research prototyping
*and* the final, safety-critical system. Then perhaps the prototype
could just be cleaned up and "hardened" for the end product rather
than rewritten in another language -- by programmers in another state
who may fail to understand many of the details that the prototype
developer agonized over.

You might have a look at Business Shell <http://www.pegasoft.ca/bush.html>
which is based on Ada.

Mel.
 
L

Luis Zarrabeitia

2. There is also nothing inherent in a dynamic OO language that says
that class descriptors have to be mutable, any more than strings have
to be mutable (Python has immutable strings).  I agree that being able
to modify class descriptors at runtime is sometimes very useful.  The
feature shouldn't be eliminated from Python or else it wouldn't be
Python any more.  But those occasions are rare enough that having to
enable the feature by saying (e.g.) "@dynamic" before the class
definition doesn't seem like a problem, both for encapsulation

Why don't you do it backwards?
You *can* implement a metaclass that will remove the dynasmism from its
instances. Do it - I can give you a starting point if you wish.

But most of us are very happy with the dynamic nature of python... I chose
python _because_ of it.
and because it can also improve performance.

Btw, for performance, there is __slots__, with the side-effect that it forbids
attribute creation 'on the fly'.
 
L

Luis Zarrabeitia

Russ P. wrote:
public = no leading underscore
private = one leading underscore
protected = two leading underscores

Aren't the last two reversed?

protected = one leading underscore
[both you and your subclasses should access it]
private = two leading underscores (name munging)
[only you should access - implementation detail.]
 
L

Luis Zarrabeitia

Should Python get strict and enforce access control
of object members ? No. Why ? I can think of several
reasons.

Give me one use-case where you strictly require
that members of an object be private and their
access enforced as such ?

Devil's advocate here - I think I can give you one:

when you need to share some objects with potentially untrusted code (like, a
plugin system). You can't, and you shouldn't, expect that the user will know
what plugins he should or shouldn't load, and you shouldn't blame him/her
when your app stops working because you failed to protect it's internals from
malicious plugins (think web browser).

Of course... in that scenario, the public/private distinction is the least of
the concerns... and whatever is done to solve them will likely make
irrelevant if the members are private or public.

But, for trusted code? Or at least code known at compile time? It's just not
worth it... pylint should take care of that - and if it doesn't, the OP
should go fix it.
 
P

Paul Rubin

Luis Zarrabeitia said:
when you need to share some objects with potentially untrusted code (like, a
plugin system). You can't, and you shouldn't, expect that the user will know
what plugins he should or shouldn't load, and you shouldn't blame him/her
when your app stops working because you failed to protect it's internals from
malicious plugins (think web browser).

Python is not set up for this even slightly. Java attempts it, with
mixed success.
 
L

Luis Zarrabeitia

Russ:

1. Quit while you're ahead.
2. OOP is encapsulating data and functionality into a single grouping
(object).
3. Other features more recently developed by OO languages such as
Polymorphism, Access Control (a type of encapsulation), Inheritance
and Multiple Inheritance are all irrelevant and OO languages either
implement all or a subset of these features and each do so
differently.

To further your point, I'd say that python _doesn't_ have polymorphism. It
doesn't need it - the natural, expected, "OOP" behavior is always there, you
cannot break it. A dog will always bark and a cat will always meow,
regardless of the context and the inheritance relation between a cat and a
dog (there should be none, but I couldn't think of a better example than the
broken 'a cat is a dog'... please bear with me). If the very concept of
polymorphism is superfluous in python, would that make python 'less' OOP?

Judging by this thread, I'd guess that Russ believes that languages like C#
are closer to his OOP ideal... and guess what, C# not only needs a word for
the concept of "objects should behave as you expect them to behave - we want
no barking cats, ever", but it is even not polymorphic by default (the
cursed "virtual" keyword).
 
P

Paul Rubin

Terry Reedy said:
The question is where such checks should be. Guido prefers separate
checkers (PyChecker, PyLint) rather than in the interpreter.

Again, there have to be some language extensions to communicate the
necessary info to the external tool. Python 3.0 begins to do that,
but as others have mentioned, it's still in a formative state while we
get more experience with it. The other angle is that the compiler can
use static knowledge about the program to make the program run faster,
so if the checks are in an external tool, there has to be
communication in both directions to make use of that.
 
P

Paul Rubin

Luis Zarrabeitia said:
Why don't you do it backwards?
You *can* implement a metaclass that will remove the dynasmism from its
instances. Do it - I can give you a starting point if you wish.

That's kind of interesting, how does it work?
But most of us are very happy with the dynamic nature of python... I chose
python _because_ of it.

I like it too, since it is indispensable in some situations. But,
those situations are uncommon enough that I don't mind typing a few
extra keystrokes to turn the dynamism on.
Btw, for performance, there is __slots__,

That is a good point, we somehow lost sight of that in this thread.
with the side-effect that it forbids attribute creation 'on the
fly'.

I have had the impression that this is a somewhat accidental side
effect and shouldn't be relied on.
 
B

Bruno Desthuilliers

Paul Rubin a écrit :
Part of the idea of non-dynamic attribute sets is to make the program
run faster, not slower.

Russ argument was about "good engineering", not about raw perfs. FWIW,
_you_ may be willing to trade dynamism for raw perfs, but there are
probably some people here that won't agree.
 
B

Bruno Desthuilliers

Paul Rubin a écrit :
But, if something is done by convention, then departing from the
convention is by definition unconventional. If you do something
unconventional in a program, it could be on purpose for a reason, or
it could be by accident indicating a bug.

I don't understand why some folks spew such violent rhetoric against
the idea of augmenting Python with features to alert you automatically
when you depart from the convention, so that you can check that the
departure is actually what you wanted. A lot of the time, I find, the
departures are accidental and automated checks would save me
considerable debugging.

Given that the convention for "protected" attributes in Python is to
prefix them with an underscore, I fail to see how one could
"accidentally" mess with implementation details. Typing a leading
underscore is rarely a typo.

Oh, BTW, IIRC, there are a couple lint-like apps for Python, some of
them being able to warn you about most of these (potential) problems.
 
P

Paul Rubin

Bruno Desthuilliers said:
Russ argument was about "good engineering", not about raw perfs. FWIW,
_you_ may be willing to trade dynamism for raw perfs, but there are
probably some people here that won't agree.

Obviously there will never be total unanimity about every tiny thing.
I haven't anywhere in this thread as far as I know suggested
eliminating dynamism from Python, which would be in "that's not Python
any more" territory. But, in the dozens of class definitions I write
in any given day of coding, I might use the dynamism we're talking
about in 1% of them at most. If having to type a few extra keystrokes
on that 1% improves program reliabiity AND performance, it certainly
seems worth it to me.
 
P

Paul Rubin

Bruno Desthuilliers said:
Given that the convention for "protected" attributes in Python is to
prefix them with an underscore, I fail to see how one could
"accidentally" mess with implementation details. Typing a leading
underscore is rarely a typo.

We are talking about the accidental creation of new attributes in
places outside the initializer. The underscore convention does
nothing to prevent that.
 
L

Luis Zarrabeitia

That's kind of interesting, how does it work?

Proof of concept, that breaks on inheritance (can't call 'super'), but it took
me just a few minutes to cook. If you aren't that paranoid, you could get rid
of the 'currentframe' and 'code' hacks. This creates a class "MyClass" which
instances cannot be modified. I once gave my students the homework of
creating a metaclass that would type-check all the assignments to its
members - so that the types wouldn't change.

========
import inspect

class ImmutableType(type):
def __init__(self, *args, **kwds):
super(ImmutableType, self).__init__(*args, **kwds)
initmethod = self.__init__.im_func
def setattr(instance, attr, value):
callee = inspect.currentframe(1) #letting the initializer
if callee.f_code is initmethod.func_code: #initialize the object
super(self, instance).__setattr__(attr, value)
else:
raise Exception("Object is immutable")
self.__setattr__ = setattr # Heh, I'm adding a dynamic attribute :D


class MyClass(object):
__metaclass__ = ImmutableType
a = 5
def __init__(self, value):
print "assigning b"
self.b = value
print self.b

m = MyClass("can't change")

print m.a, m.b # these work
m.b = 6 # and these dont.
m.c = 8
==========

I like it too, since it is indispensable in some situations. But,
those situations are uncommon enough that I don't mind typing a few
extra keystrokes to turn the dynamism on.

I find the opposite to be true.
I _usually_ want the dynamism. Even if I'm not using it - I rely on the
dynamism to be there for when I need it.
That is a good point, we somehow lost sight of that in this thread.


I have had the impression that this is a somewhat accidental side
effect and shouldn't be relied on.

Yes, accidental side effect.

But I see no _necessary_ harm on tacking extra attributes to an existing
object - specially if you are going to use them pretty close to the creation.
I use them, a lot, specially when writing decorators... Many times I just
want to 'mark' the decorated functions so I can inspect those marks later.
I'd rather have a semi-private namespace for each pair ([group of]calling
function, object), but it is way easier (and so far, maintanable) to just
add an appropriately named dynamic attribute to the object.

Of course there can be harm - but the fault lies on the user and not the tool.
I specially dislike that I can't add dynamic attributes to an object().
 
B

Bruno Desthuilliers

Russ P. a écrit :
I think you are the one who is confused. Part of the problem here is
that the term "encapsulation" has at least two widely used meanings
(in the context of programming). In one sense, it just means grouping
data and methods together. In another sense, it means restricting the
client's access to data or methods.

The second is named "data hiding". And while it's a mean to _enforce_
encapsulation, it is not encapsulation by itself. Encapsulation is about
making clear what's part of the public interface and what's
implementation detail - IOW, it's about decoupling client code from
implementation. Nothing in this _requires_ data hiding.
Someone earlier on this thread
tried to claim that the first meaning applies to OOP, but Wikipedia
(and many other sources) say just the opposite.

You can choose to trust everything you read on wikipedia. You can...
wrt/ what's OO, the only commonly accepted definitions are:

1/ objects are defined by an identity, a state and a behaviour
2/ objects communicate by sending messages to each other

People here are trying to claim that the leading underscore
conventions used with Python are essentially equivalent to
encapsulation. That is nonsense, of course.

Your POV.
But the point is that if you don't like
encapsulation,

I do like it. What I don't like is useless language-enforced restrictions.
then by definition you don't like OOP. You may like
certain features of OOP, but you don't like it in general. That's
about all their is to it.

And by the way, please don't bring up the canard that I am some kind
of OO zealot. I think OO is overrated, and I don't Java, in part
because it forces everything to be OO. The issue here is not my
personal opinion of OOP. This issue is one of widely accepted
definitions within the OO community.

Another widely accepted definition within the OO community is that C++
is an OO language because it has classes and data-hiding, and that
Javascript is not because it has none of them.
Of course it's not a "requirement that programming languages must
implement." It's only a requirement if they want to be OO languages.

Neither. The only requirements for being an OOPL are stated above.

You can claim it, yes. OTHO, I can claim that Java is not strictly
object oriented since it has non-object types.

In both cases, this is just plain meaningless. There's no closed,
well-defined theory, no mathematical model behind "OO" (like there are
for functional programming or for the relational model). So you just
can't apply "strictly" to OO. It's just nonsense.

IOW : "this is the HolyTruth(tm), because I said so". Sorry, won't work.

Yes. And FWIW, there are OO libraries and programs written in plain C.
Ever heard of GTK+ ?

For a somewhat partial definition of "good software engineering". Mine
is that anything that leads to a correct, robuste and maintainable
program is good engineering, anything else is not. From this POV, and
given the proven fact that the bug/LOC ratio is nearly constant whatever
the language, anything that adds accidental complexity makes the program
less robust and less maintainable, and as such is _not_ "good software
engineering". Sorry for being pragmatic !-)
You're kidding, right? Think about a ten-million line program being
developed by 100 developers.

And ? Except that this code surely needs urgent surgery (sorry, I meant
refactoring), I don't see what the size of the project or the team has
to do with it. You'll find successful "monster" projects written in
languages that are even more permissive than Python (C anyone ?), and
failed "monster" projects written in highly unpermissive languages like
Java or ADA.
 
P

Paul Rubin

Bruno Desthuilliers said:
You'll find successful "monster" projects written in
languages that are even more permissive than Python (C anyone ?),

Could you name one written in C? Anyway, C is far less safe than
Python in some ways, but has lots more compile time checking.
 
P

Paul Rubin

Luis Zarrabeitia said:

That project may be successful in terms of having a lot of users, but
much less so in terms of code reliability (see all the CERT bulletins
about it). Also, it is much smaller than 10 MLOC, I think.
 
B

Bruno Desthuilliers

Paul Rubin a écrit :
Obviously there will never be total unanimity about every tiny thing.

Indeed !-)
I haven't anywhere in this thread as far as I know suggested
eliminating dynamism from Python,

Nope, but your suggestion would have the same practical result as far as
I'm concerned.
which would be in "that's not Python
any more" territory. But, in the dozens of class definitions I write
in any given day of coding, I might use the dynamism we're talking
about in 1% of them at most.

Indeed : these are the classes _you_ (as a library author), write, so
they work as _you_ (as a user of these library) expect them to work.
If having to type a few extra keystrokes
on that 1% improves program reliabiity AND performance, it certainly
seems worth it to me.

If it makes simple thing overly complicated, it certainly seems _worse_
to me !-)
 

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

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,006
Latest member
LauraSkx64

Latest Threads

Top