is python Object oriented??

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Wed Feb 4 05:12:40 EST 2009


Steven D'Aprano a écrit :
> On Tue, 03 Feb 2009 12:09:46 +0100, Bruno Desthuilliers wrote:
> 
>>> I love Python, and I'm greedy and want it all: I want a dynamic,
>>> easy-to- use language *and* a compiler that can protect me from myself
>> That's not what compilers are for.
> 
> So you say.

While it's quite clear that a compiler for a statically typed language 
can catch at least some type errors, this is still not what a compiler 
is for. A compiler is here to compile you source code into a suitable 
representation for the execution environment. And FWIW, some compilers 
are rather weaker than Python when it comes to "protecting you from 
yourself".

>  
>>> and bad data.
>> I definitly fail to see how a compiler could protect you from *runtime*
>> issues ???
> 
> I'm surprised you can't. Any time a compiler prevents an error by 
> detecting it at compile-time (say, attempting to store a 96-bit float 
> into the memory space allocated for a 32-bit int),

Oh, you meant "type error". But this is a programming error, not "bad 
data". "bad data" is something you get (usually from the outside world) 
at runtime only. Well, the way I understand it, at least.

> 
> Perhaps what you are thinking is that I meant compilers can protect you 
> from "all" runtime issues. That would be silly. Although, in principle, 
> we can get close, for some definition of "close".
> 
> 
> Here's a toy function, and a specification:
> 
> def inverse(x):
>     return 1.0/x
> 
> Specification: input must be a float, output must be a float.
> 
> Is that function correct? No, because it will raise an exception if 
> x==0.0. Python's compiler is dumb and will allow you to write incorrect 
> functions, but a smart compiler could look at that function and see that 
> it was incorrect. The fix would then be to change the code, or the 
> specification, or both.

Ok, let's see. What happens if you pass 0.0 to the function as-is ? Yes, 
indeed, you get a runtime error. Now what happens if you add error 
handling to the function itself ? What will the error handler do ? Yes, 
raise a runtime error. So far, I don't see any gain here. No, no, don't 
answer yet. Sure, what you need here is a compiler that can inspect the 
whole code source using this function to make sure it is always properly 
invoked. Mmm, wait - will this work with shared libs ? I'm afraid not. 
Ok, so you have to change the specification to : "input must be a 
non-zero-float", and use the type system to define non-zero-float type.

> Smart compilers turn some runtime errors into compile-time errors.

Indeed.

> The 
> earlier you catch the error, the easier it is to fix it.

Indeed.

> Now, that's a toy example. Languages like Ada make correctness proofs, 
> well, perhaps not easy, but merely difficult compared to impossible for 
> languages like Python.

Indeed. And that's fine : if we want maximum type safety and 
as-possibly-proved code, we know which tool to use. Now good luck doing 
web development, system admin, app scripting and quite a lot of other 
things (well, perhaps more that 80% of ordinary application programming) 
in Ada.

Can you understand that not everybody needs maximum type safety / 
correctness proof etc for all his code ? That all this "security" stuff 
comes with a price that may not be worth paying ?

> To bring it back to private/public attributes, side-effects make 
> correctness proofs difficult. Modifications of attributes are side-
> effects.

Then use a functional language !-)

> When attributes are subject to being modified by arbitrary code, 
> it is harder to reason about the correctness of the code:

Indeed. Not the right tool, obviously. OTHO, it makes it way easier to 
use as glue between different, sometimes not highly compatible components.

(snip)

> There are two usual approaches to dealing with that problem which are 
> available to Python programmers:
> 
> (1) Paranoia. Make the developer responsible for checking everything all 
> the time:


Paranoiacs (also known as control-freaks) are not happy using Python. 
They usually prefer Ada or, at least, Java.

>     def invert(self):
>         x = self.x
>         if isinstance(x, float) and x:
>             return 1.0/self.x
>         else:
>             raise MyError('post-condition x a non-zero float violated')


The correct solution is indeed to make x a property with a sanity check 
in the setter - in which case you'll have a useful traceback - or as a 
read-only property, or even better to just declare it as implementation 
(naming it _x).

> 
> (2) Hope the error never occurs, and if it does, let the caller deal with 
> it.

If the attribute is either a read-only property or an implementation 
attribute, then the guy that messed with it is responsible for the 
possible consequences. That's the contract, yes.

> Hopefully you aren't your own caller.

I'm usually the first user of my own libs, and my coworkers comes 
immediatly after. IOW, I eat my own dogfood, thanks.

> That's often the Python approach.

As I explained above, the "Python approach" is actually a bit different.

In your example code, you explicitely declared x as a *public* 
attribute. Which is not wise - whatever the language - if you have to 
maintain invariants on this attribute. Make it either an implementation 
attribute or a read-only property.

(snip usual stuff about nuclear disasters, x-ray-overdosed patients etc)

> There is a third strategy, sadly not available to Python programmers: 
> prevention by catching potential errors at compile-time. (Python does 
> catch some errors at compile-time, but only syntax errors.)

Yes. Because *everything* else happens at runtime. Remember, even "def" 
and "class" are executable statements.

> If x can only 
> be modified in a few places, (that is, it is effectively hidden or 
> private) then it is much easier to reason about program correctness, 
> avoid bugs, and debug those bugs which do occur.

Would you then say that Ruby has "real privates" attributes ?


> No, this is not a panacea which will prevent every imaginable bug.

Indeed.

> Nor is 
> it a replacement for unit-testing (which also does not prevent every 
> imaginable bug). 

Neither.




More information about the Python-list mailing list