python versus __python__

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

python versus __python__

Arthur-27
Kirby -

>PS:  since you've been studying subclassing primitive types using __new__,
>maybe you could show us a user-defined floating point type that reports two
>numbers equal if their absolute value difference is less than e.  Anyone?

My studies on the subject of subclassing the complex type have been quickly
abandoned - it becoming clear that the fact the .real and .imag are read-only
defeats the ideas I had for it.  I guess I might have tried harder to see if
one could override that behavior in a subclass, but my decision to move on
is based on the fact that if what I like to think I am pursuing is simplicity,
changing the  fundamental behavior of a built-in, even if doable, would
not seem to be a path to it.

But as these dead-end explorations usually do, got me thinking about things not
previously confronted.  Like the simple question of what is "float" fundamentally,
a function - as in float(1) - or a numeric type.  And by subclassing "float", is one
subclassing a function or a type.

Is just some shadowing of a name going on in the netherworld, or are the function
and type more intimately related in that realm?

Us non C programmers look forward to PyPy for the view of the netherworld it will
give us.  In truth I expect PyPy to bring a new burst of creative energy to the
Python world, just by opening up the possibility of lower level exploration to
a wider group of folks.

As the answer to most of the "why Python" questions that we all try to answer
on some technical level, in the end - IMO - boil done to largely that, the creative
energy surrounding it.

Perhaps that understanding should provoke me into whining less about the moving
target that Python seems sometimes to be.  Perhaps Guido understands either consciously or
intuitively that less openness to change - with all the downsides of such change -
would subvert that essential energy aura in which Python persists.

Art



_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: python versus __python__

Arthur-27
Arthur wrote:

>Us non C programmers look forward to PyPy for the view of the netherworld it will
>give us.  In truth I expect PyPy to bring a new burst of creative energy to the
>Python world, just by opening up the possibility of lower level exploration to
>a wider group of folks.
>  
>
So I go the next step, download PyPy, and get at app_complex.py  - which
is the pypy implementation of the Python complex function, implemented
in Python - all as advertised.

Which is nicely transparent to someone who can read Python well-enough -
as advertised.

Not too surprisingly, it uses our friend property to implement the read
only aspect of .real and .imag, so that by simply commenting out the
property functions I seem to have what I think I want, the ability to
work with a complex number object, with the ability to write directly to
.real and .imag.

Probably from there I rename it from "complex" to "Complex" - I like
case sensitivity for these kind of reasons - so that I remember I am
working with the Python function not the built-in function, then inherit
from it as I was intending to do with the builtin, and then plug it into
PyGeo.  Sacrificing performance - no doubt - with the upside of running
it through some paces (the pypy module acknowledges it is not well
tested, and if there are any issues perhaps they will be uncovered, and
contributing to pypy in any small way seems worthwhile),  seeing if the  
architecture I had in mind is actually sensible, and seeing if I
discover why there was a decision to make .real,.imag read only as to
the builtin.

Yup - pypy is going to change things.

Art

_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: python versus __python__

Arthur-27
Arthur wrote:

> Arthur wrote:
>
>> Us non C programmers look forward to PyPy for the view of the
>> netherworld it will
>> give us.  In truth I expect PyPy to bring a new burst of creative
>> energy to the
>> Python world, just by opening up the possibility of lower level
>> exploration to a wider group of folks.
>>  
>>
> So I go the next step, download PyPy, and get at app_complex.py  -
> which is the pypy implementation of the Python complex function,
> implemented in Python - all as advertised.
>
> Which is nicely transparent to someone who can read Python well-enough
> - as advertised.

And which, BTW, serves as a nice reference for techniques of operator
overloading - which I have always found get a bit tricky once one gets
beyond the simplest form of it.  I had used what I find in Numeric's
UserArray as my previous reference - nice to have something else to
study a bit.

Art



_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: python versus __python__

Scott David Daniels
In reply to this post by Arthur-27
Arthur wrote:
> My studies on the subject of subclassing the complex type have been quickly
> abandoned - it becoming clear that the fact the .real and .imag are read-only
> defeats the ideas I had for it.
Ahh: complex is (as are bool, int, long, string, and unicode) immutable.
Changing such types to be mutable is "nasty" -- reuse of an immutable is
done by referring to the same object, while reuse of an immutable needs
a copy.  If you do make one of these mutable, be sure to eliminate the
hash function, or you won't be able to have it a key in a dictionary.
Typically immutables are considered "identical" if they have identical
state.  Conceptually there should be no way to tell the difference
between two distinct but equal immutables and the same immutable used
twice.  In fact, you can just check if id(one) == id(other), but that
is "cheating" -- the "no way to tell" avoids precisely this trick.

By the way, before you get too involved in playing with this stuff,
there is a nasty surprise waiting to bite you.  When you are comparing
ids, be sure to compare ids of named things, not expressions.  You might
be surprised to learn: id(math.log(math.pi)) == id(math.log(math.e))!
It is fun to try to figure out why.  I'll post the answer tomorrow if
nobody gets it by then.

> But as these dead-end explorations usually do, got me thinking about things
> not previously confronted.  Like the simple question of what is "float"
> fundamentally,  a function - as in float(1) - or a numeric type.  And by
> subclassing "float", is one subclassing a function or a type.
 > Is just some shadowing of a name going on in the netherworld, or are
 > the function and type more intimately related in that realm?

If you define a class named PyGeoTriangle, you create new instances with
PyGeoTriangle(<some args>).  Same with types (especially as we head into
the brave new world of "new-style objects").  The changes in Python are
heading towards a unification of types and classes, but that cannot
fully happen until Python 3.0 (at least).  Why not? -- old-style classes
and new-style classes behave differently under the covers.  So
eventually (and in many cases now), a type name is just a predefined
new-style class name.

New-style classes and standard types can be made to behave quite the
same, but old-style classes cannot.  Unfortunately, some basic parts
of Python (Exception comes to mind) use old-style classes.  Code that
people have written to run with Exception, living in some dark lab in
northern New Jersey (for example), would break if Exception were a
new-style class.  We cannot make the change except when we declare an
"incompatible change".  The reason for making the change to new-style
classes throughout is to simplify Python's design (and the model the
user must have in his head).

> Us non C programmers look forward to PyPy for the view of the netherworld it will
> give us.  In truth I expect PyPy to bring a new burst of creative energy to the
> Python world, just by opening up the possibility of lower level exploration to
> a wider group of folks.
>
> As the answer to most of the "why Python" questions that we all try to answer
> on some technical level, in the end - IMO - boil done to largely that, the creative
> energy surrounding it.
>
> Perhaps that understanding should provoke me into whining less about the moving
> target that Python seems sometimes to be.  Perhaps Guido understands either consciously or
> intuitively that less openness to change - with all the downsides of such change -
> would subvert that essential energy aura in which Python persists.

--Scott David Daniels
[hidden email]

_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: python versus __python__

Arthur-27
Scott David Daniels wrote:

>Arthur wrote:
>  
>
>>My studies on the subject of subclassing the complex type have been quickly
>>abandoned - it becoming clear that the fact the .real and .imag are read-only
>>defeats the ideas I had for it.
>>    
>>
>Ahh: complex is (as are bool, int, long, string, and unicode) immutable.
>Changing such types to be mutable is "nasty" -- reuse of an immutable is
>done by referring to the same object, while reuse of an immutable needs
>a copy.  
>
Getting one's arms around all the practical implications of these issues
related to mutable, immutable - understanding when one should want to
retain object  identity, and when one should want to break it, the full
implications of these decisions,  howto  implement one's intentions -
is, on one hand - I find, fundamental to getting things to actually
happen in Python as one intends, and on the other hand , challenging. It
is the fundamental reason I chafe a bit when Python is described as "easy".

Because I have had  trouble with these issues from day one, it ain't day
one anymore, I still have some troubles with them and I prefer to think
that it is challenging over thinking that I am dumb.

I am going down the road of the mutable complex number with my eyes
(half) open precisely because I want the ability to change the value of
a complex number object (and it's subclasses), without changing the
identity of the object.

Is that so wrong ;)

>If you define a class named PyGeoTriangle, you create new instances with
>PyGeoTriangle(<some args>).
>
The connection of what you are saying here to the issue on which I am
particularly confused  is - well -  confusing, to me.

In Arthur's head there is the numeric type "float", and there is the
function float() - both built in.  And in Arthur's head, while  
functions are first class objects in Python they are objects of a
different nature than type in the sense of numeric type.  So in some
sense what I am not grasping is how class/type unification can be
inclusive of verb - i.e, float(1) -  and  noun - i.e., type(1.) -
unification - which in Arthur's head, is something else again.

Art



_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: python versus __python__

Scott David Daniels
Arthur wrote:
> Scott David Daniels wrote:
> ...
> Getting one's arms around all the practical implications of these issues
> related to mutable, immutable - understanding when one should want to
> retain object  identity, and when one should want to break it, the full
> implications of these decisions,  howto  implement one's intentions -
> is, on one hand - I find, fundamental to getting things to actually
> happen in Python as one intends, and on the other hand , challenging. It
> is the fundamental reason I chafe a bit when Python is described as "easy".
Ah, but you are concentrating on fundamental issues of language design
which are, in fact, subtle.  Normally the user of a language simply
accepts the determination of the designer about what is mutable and
what is not, and goes on from there.  I think these issues are indeed
fascinating, but they are issues of language design, not even issues
for the __python__ class.  Python allows you to play with these issues
in your own classes, few other languages allow you that freedom.

> Because I have had  trouble with these issues from day one, it ain't day
> one anymore, I still have some troubles with them and I prefer to think
> that it is challenging over thinking that I am dumb.
Well, you are right.

> I am going down the road of the mutable complex number with my eyes
> (half) open precisely because I want the ability to change the value of
> a complex number object (and it's subclasses), without changing the
> identity of the object.
In the first Fortran (and for a number of versions later), you called
"subroutines" with all arguments "by reference."  There were people
who would abuse this ability to change constants (which were shared
across a single "compilation unit") to find compact ways to alter
things that were not properly variables.  This brings new meaning
to "1+1=4 for sufficiently large values of 1".

>>If you define a class named PyGeoTriangle, you create new instances with
>>PyGeoTriangle(<some args>).
>
> The connection of what you are saying here to the issue on which I am
> particularly confused  is - well -  confusing, to me.

I'm trying to point out that you understand perfectly that some things
are both objects and callable; you just don't realize that you do.  The
most obvious example is a class, while the second (and far less) obvious
is an instance of a class with a __call__ method.

In the case of a class that you have defined, you can use the class name
itself in calls to things like "isinstance,"

> In Arthur's head there is the numeric type "float", and there is the
> function float() - both built in.  And in Arthur's head, while  
> functions are first class objects in Python they are objects of a
> different nature than type in the sense of numeric type.  

> So in some sense what I am not grasping is how class/type unification
> can be inclusive of verb - i.e, float(1) -  and  noun - i.e., type(1.)
> - unification - which in Arthur's head, is something else again.
The magic trick of class / type unification is: we both need to name
types (they must have existence as objects) for use in some functions,
and we need to provide constructors for instances of that type.  This
is the same situation we are in about classes.  The class situation is
resolved by making "special" methods that get invoked when the class is
used to call


--Scott David Daniels
[hidden email]

_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: python versus __python__

Scott David Daniels
In reply to this post by Scott David Daniels
Scott David Daniels wrote:
> By the way, before you get too involved in playing with this stuff,
> there is a nasty surprise waiting to bite you.  When you are comparing
> ids, be sure to compare ids of named things, not expressions.  You might
> be surprised to learn: id(math.log(math.pi)) == id(math.log(math.e))!
> It is fun to try to figure out why.  I'll post the answer tomorrow if
> nobody gets it by then.

With CPython, expressions, once used and dereferenced, recycle their
objects.  If you don't hold a reference to the value created by
calculating the log of pi, it will get recycled once id is done
with is arg.  The available storage is lying around when log(e)
is calculated and so is reused.  Such things don't happen when
working with small integers, because Python caches them to save
some creation time.

So,
     id(math.pi + 1.0) == id(29. / 7.)

but then again:
     id(math.pi + 5280.0) == id(1. / 9.)

--Scott David Daniels
[hidden email]

_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: python versus __python__

Beni Cherniavsky-2
On Mon, 2005-10-24 at 20:24 -0700, Scott David Daniels wrote:

> With CPython, expressions, once used and dereferenced, recycle their
> objects.  If you don't hold a reference to the value created by
> calculating the log of pi, it will get recycled once id is done
> with is arg.  The available storage is lying around when log(e)
> is calculated and so is reused.  Such things don't happen when
> working with small integers, because Python caches them to save
> some creation time.
>
> So,
>      id(math.pi + 1.0) == id(29. / 7.)
>
> but then again:
>      id(math.pi + 5280.0) == id(1. / 9.)
>
Neat :-)

Of course, the proper way to compare object identity is not the
__low_level__ `id()` function but the ``is`` operator:

>>> (math.pi + 1.0) is (29. / 7.)
False
>>> int('99') is int('99') # small integer
True
>>> int('100') is int('100') # big integer
False

[``is`` works properly because both expressions are evaluted before the
``is`` operator is evaluted and only then the 2 values are
garbage-collected.  With `id()`, the 2 values could be reclaimed
immediately because only the address is needed for the ``==``
comparison.  The fact that `id(foo)` does not reference `foo` is the #1
source of confusion regarding `id()`.]

_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig
Reply | Threaded
Open this post in threaded view
|

Re: python versus __python__

Scott David Daniels
Beni Cherniavsky wrote:

> On Mon, 2005-10-24 at 20:24 -0700, Scott David Daniels wrote:
>
> Of course, the proper way to compare object identity is not the
> __low_level__ `id()` function but the ``is`` operator:
>
>>>>(math.pi + 1.0) is (29. / 7.)
>
> False
>
>>>>int('99') is int('99') # small integer
>
> True
>
>>>>int('100') is int('100') # big integer
>
> False
>
> [``is`` works properly because both expressions are evaluted before the
> ``is`` operator is evaluted and only then the 2 values are
> garbage-collected.  With `id()`, the 2 values could be reclaimed
> immediately because only the address is needed for the ``==``
> comparison.  The fact that `id(foo)` does not reference `foo` is the #1
> source of confusion regarding `id()`.]
That won't save you from surprises when walking in subtle territory.

For example:  # Distributive law
 >>> -(-3 - 7) is (- -3) - -7
True

But:
 >>> -(3 + 7) is -3 - -7
False

The difference is the aforementioned caching trick -- small positive
(and a few negative) integers are cached, the exact range is, I think
-5 : 100, but it is subject to change and should _not_ be remembered
(Python is free to change the number at any time; caching is an
optimization, not meant to affect the meaning of the language).

In general the "is" operator is asking about internals you should seldom
be poking around inside (playing with magic) except for the incantation
"is None" and "is not None" since there is one and only one None.  There
are, of course, times when you are concerned about "exactly this object"
and those times are when is is proper, (and id(obj) might well be a
perfectly fine value supplying a total order on such objects).

The main reason I am belaboring the point is the recent mutable /
immutable discussion: you should never concern yourself with the
identity of an immutable; they are "values" to be compared using
equality or ordering comparisons.  Two immutables built the same way
should be indistinguishable from two references to the same immutable
in properly written code.  You need immutables for dictionary keys,
because (in the implementation) structure is built based on values
of the keys.  If the values changed by mutating, your structure
would no longer reflect the values it contains (so some data would
become unreachable).
     storage = {3+4j : 1, 4+3j : 2}
     Suppose you negated the imaginary part of the object which is the
key to the value 1.

  What should storage[3+4j] (where 3+4j is freshly calculated) return?
  What should storage[3-4j] (where 3-4j is freshly calculated) return?

Such problems are not so much implementation issues (although they do
reveal the implementation) as problems with the definition of the
language.  That's why this is subtle territory.

--Scott David Daniels
[hidden email]

_______________________________________________
Edu-sig mailing list
[hidden email]
http://mail.python.org/mailman/listinfo/edu-sig