[Edu-sig] Sticky-note Analogy

kirby urner kirby.urner at gmail.com
Fri May 9 20:06:21 CEST 2008


On Fri, May 9, 2008 at 9:21 AM, Mark Tolonen <metolone+gmane at gmail.com> wrote:
>
> "kirby urner" <kirby.urner at gmail.com> wrote in message
> news:f604188c0805090730v2163d12dw9970fcf4b96220ac at mail.gmail.com...
>>
>> I've suggesting seeing 8 as a name only briefly, temporary gestalt
>> switch, then go back to seeing it as a literal, kind of like a name
>> in that you can do dot notation on it, i.e. there's an underlying
>> object that's responsive to these triggers (like 8 .__add__(5)
>> instead of just 8 + 5).  But is the underlying object "anonymous"?
>>
>> It has a memory location:
>>
>>>>> id(8)
>>
>> 12015636
>>
>>>>> id('8')
>>
>> 13259744
>>
>> And I'm able to refer to it.  I didn't make up a name for it, like
>> eight, because I didn't need to, it's already permanently
>> accessible through 8.
>>
>
> Numbers are just language syntax to create objects.  If they aren't assigned
> a name, they disappear.
>

I think that's way ahead of where most C programmers would start, so
yes, agreed.

On the other hand, 8 doesn't disappear but remains equally available
in all scopes.

However, it's a read-only object, so there's no sense of other handles,
like eight (after eight = 8) communicating state changes to other
objects.  There's no 8 .value =  9 or such nonsense.

But I like your picture of 8 "giving birth" (triggering a constructor
somewhere, almost like 8 = 8 ( ) except you don't need that step  ).

Intuitively, we know 88592389182 can't "already be there" before we
start applying dot notation to the thing.  It must be created "out of
the blue" -- and so the idea of a birth event (ala __new__ and __init__).

And let's not forget strings like 'abc', other literals.

This thing about 'ABC'.lower() == 'abc' returning True is that object
'ABC', in the time it exists, has all these inherited magical powers
in virtue of being type string -- lots of talent, lots of vim.

In the C world, there's this strong prejudice against what's called "data"
(like a string) having executive powers. "Mere data" shouldn't be able
to "run code" as it were.

But in Python, where "everything is an object" we think of 8 + 5 as
triggering 8's "add method" i.e. running some code, maybe a lot
of it (multiplication gets complicated, may involve trig in some
algorithms).

Is >>> 8 "giving birth" or mentioning something "already born"?  We
might take an empirical approach to that question:

>>> id(98204958298347923)
12756632
>>> id(98204958298347923)
12756728
>>> id(98204958298347923)
12755816
>>> id(8)
12015636
>>> id(8)
12015636
>>> id(8)
12015636
>>> id(8)
12015636
>>> id(20)
12015492
>>> id(20)
12015492
>>> id(200)
12017300
>>> id(200)
12017300
>>> id(200)
12017300
>>> id(2000)
13756860
>>> id(2000)
13756788
>>> id(2000)
13541792

I'd say 8 is "already born" whereas 2000 is "created on the fly".
But this is an implementation detail so we can agree these
both amount to the same thing at the end of the day.  Literals
behave as literals, regardless of whether Python preallocates
for low numbers.

Regarding persistence:

You could easily write a whole program that executes within an
"anonymous (unnamed) class" in the sense >>> Rod( ) stays
anonymous and goes out of scope if no other name tags it.**

>>> class Main:
	def __init__(self):
		runtime()

	
>>> def runtime():
	print "A huge Python script, like Zope, runs for days"
	
>>> Main()
A huge Python script, like Zope, runs for days
<__main__.Main instance at 0x00E68558>

So Main (a name within __main__) is created as an "anonymous object"
in the sense that we don't tag it with anything else top level -- and that's
OK, because we can give birth to a Main object without bothering with
assignment, and get all the work done we need.

I mention this because I think students need to get that naming is
all about preservation or persistence through time ("saving"), and
persistence is defined against the backdrop of "scopes" -- names
going in and out of 'em (via whatever syntax -- you have some
control, might use attribute syntax yet trigger a method, per the
property feature).

We've already established that what goes on in a function call is
essentially assignment, i.e. passed names do the same kind of
thing as when we just go x = y, however we choose to characterize
it (by value? by reference? trying to shoehorn into K&R categories
seems a little misguided from the beginning as I think we should
be coaching C programmers into *escaping* from K&R's conceptual
model -- which is about a different language, not so apropos).

A bias in Python is against cluttering your namespace, which is where
those collection objects come in, with APIs for communicating with
pretty much any number of objects through a common switchboard.

But then, that's a bias in almost any good programming language,
so Python is inheriting from (benefiting from) earlier work (no question
C an inspiration, though Guido circles ABC mostly, also in the sense
of not wanting to repeat some mistakes, of providing new freedoms).

Literals are not bound by scope, in the sense of their being equally
available in all contexts.  They're "already saved" but go ahead and
tag 'em with variables if you wish.  Names are definitely scope-bound
mortals in contrast, globals coming closest (not saying globals
are better -- they often get in the way, add unnecessary overhead).

Literals are *like* names in being tokens supporting dot notation,
other syntax associated with named objects (depends on the type,
exactly what syntax you might get away with).

Mental exercise:

Imagine using Unicode greek letter pi (lowercase) as a literal in
Python, such that pi(1000) would spit back pi to 1000 significant
digits and so on, but also pi + 1 would give 4.14159 and so on
i.e. it behaves like a Decimal type (which let's say it is, under the
hood).

This would be a change to the language specification, to offer
such a pi (greek letter) as a literal across all scopes.

On the other hand, there's already nothing to stop a coder from
offering precisely this feature in a 3rd party module, as Unicode
greek letter pi as already available for naming a class.

from trig import pi  # <-- greek letter

would be all you'd need for this new "literal" (actually name)
to be available.

Which is why there's no need to enhance the Python
language specification with such a beast -- it's already allowed,
may be out there in some Python 3.x code already (not
quite the same as math.pi, but usable in all the same ways,
as input to trig functions etc.).

Kirby

** note that at birth, an object can bootstrap itself into becoming a
global, even if the programmer doesn't do explicit assignment at
birth:

>>> class Foo:
	def __init__(self):
		global r
		r = self
	def __repr__(self):
		return 'Some object at %s' % str(id(self))

	
>>> Foo()
Some object at 15106896
>>> r
Some object at 15106896


>>>> x=1000
>>>> y=x
>>>> z=x
>>>> y is z
>
> True
>
> x is the name of an object.  y and z also are names for that object.
> 1000 is not a name:
>
>>>> x=1000
>>>> y=1000
>>>> z=1000
>>>> x is y
>
> False
>>>>
>>>> x is z
>
> False
>>>>
>>>> y is z
>
> False
>
> a new object is created each time.
>
> -Mark
>
> P.S. Note, at least in CPython, that same example won't work for small
> numbers because of an implementation detail that caches the common 'small
> number' objects for performance reasons.
>
>>>> x=1
>>>> y=1
>>>> z=1
>>>> x is y
>
> True
>>>>
>>>> y is z
>
> True
>
>
> _______________________________________________
> Edu-sig mailing list
> Edu-sig at python.org
> http://mail.python.org/mailman/listinfo/edu-sig
>


More information about the Edu-sig mailing list