Re: [Edu-sig] poking around in Py3k (recycling old algebra)

2009-05-28 Thread kirby urner
Where I could see Ellipsis being used is in an OEIS-like context
(Sloan's AT&T thing) and going like [1, 12, 42, 92, ...] which you
then feed to a factory function, say get_seq.

get_seq has lookup powers (ala OEIS) and loads the right looping
construct, then gives you an itertools like thingy that spits out the
supplied values without recomputing them, then kicks in with the
generated values once the ... is encountered).

e.g.

>>> from oeis_lib import get_seq
>>> cuboctahedrals = get_seq([1, 12, 42, 92, ...]
>>> next(cuboctahedrals)
1
>>>
...

For example, an open-ended iterable for cuboctahedral numbers may be written as:

>>> class CCP:
def __init__(self):
self.value = -1
def __next__(self):
self.value += 1
if self.value == 0:
return 1
else:
return 10 * pow(self.value, 2) + 2
def __iter__(self):
return self


>>> seq = CCP()
>>> next(seq)
1
>>> next(seq)
12
>>> next(seq)
42
>>> next(seq)
92
>>> next(seq)
162

If you wanted an iterable that kicked in only after 92, you could go:

>>> from itertools import dropwhile
>>> evaldotdot = dropwhile(lambda x: x <= 92, CCP())
>>> next(evaldotdot)
162
>>> next(evaldotdot)
252
>>> next(evaldotdot)
362
>>> next(evaldotdot)
492
>>>

See:

http://www.research.att.com/~njas/sequences/A005901

(hey, links to my web site! -- oh wait, I knew that)

Kirby


On Thu, May 28, 2009 at 9:21 AM, Scott David
Daniels wrote:
> Scott David Daniels wrote:
>>
>> kirby urner wrote:
>>>
>>> ... Hey, did you know Ellipsis is a new primitive object ...
>>
>> Actually, it has been around for quite a while [broken example]
>

[fixed example]
___
Edu-sig mailing list
Edu-sig@python.org
http://mail.python.org/mailman/listinfo/edu-sig


Re: [Edu-sig] poking around in Py3k (recycling old algebra)

2009-05-28 Thread Scott David Daniels

Scott David Daniels wrote:

kirby urner wrote:

... Hey, did you know Ellipsis is a new primitive object ...

Actually, it has been around for quite a while [broken example]


Sorry, everybody, I started writing, tried the code, and editted the 
reply, rather than taking direct quotes.  In doing so, I slipped up.

I'm embarrassed enough that I'm going to re-post:

  >>> class Funny(object):
  def __getitem__(self, *args):
  return args
  >>> psuedo_array = Funny()
  >>> psuedo_array[1, ..., 10]
  ((1, Ellipsis, 10),)
  >>> Ellipsis
  Ellipsis

Just to add some actual content: I believe this was first put in
to help out array processing and heavy computation projects.  The
biggest survivors / descendants of those projects are Scipy & Numpy.

By the way, Funny is actually a fairly useful class for experiments.

--Scott David Daniels
scott.dani...@acm.org

___
Edu-sig mailing list
Edu-sig@python.org
http://mail.python.org/mailman/listinfo/edu-sig


Re: [Edu-sig] poking around in Py3k (recycling old algebra)

2009-05-28 Thread kirby urner
On Thu, May 28, 2009 at 8:22 AM, kirby urner wrote:

<< SNIP >>

> I was reading about descriptors, again per Holden workshop, and
> noticing the author adding at class level, but never making use of the
> passed instance argument, only self (inside the descriptor).
>

Below is the example from the other book, for contrast.

Note how the "instance" variable is not used in __set__ or __get__, so
whereas it looks like you're getting a new attribute there at the end
(new_att), you're not getting anything new at instance level.  David's
exposition was clearer.

==

Let's create a data descriptor, and use it through an instance:

>>> class UpperString(object):
... def __init__(self):
... self._value = ''
... def __get__(self, instance, klass):
... return self._value
... def __set__(self, instance, value):
... self._value = value.upper()
...
>>> class MyClass(object):
...attribute = UpperString()
...
>>> instance_of = MyClass()
>>> instance_of.attribute
''
>>> instance_of.attribute = 'my value'
>>> instance_of.attribute
'MY VALUE'
>>> instance.__dict__ = {}


Now if we add a new attribute in the instance, it will be stored in
its __dict__ mapping:

>>> instance_of.new_att  = 1
>>> instance_of.__dict__
{'new_att': 1}


But if a new data descriptor is added in the class, it will take
precedence over the instance __dict__:

>>> MyClass.new_att = MyDescriptor()
>>> instance_of.__dict__
{'new_att': 1}
>>> instance_of.new_att
''
>>> instance_of.new_att = 'other value'
>>> instance_of.new_att
'OTHER VALUE'
>>> instance_of.__dict__
{'new_att': 1}

=

Expert Python Programming: Learn best practices to designing, coding,
and distributing your Python software
Tarek Ziadé Copyright © 2008 Packt Publishing
___
Edu-sig mailing list
Edu-sig@python.org
http://mail.python.org/mailman/listinfo/edu-sig


Re: [Edu-sig] poking around in Py3k (recycling old algebra)

2009-05-28 Thread kirby urner
Hey, didn't know that!

And that *is* a Funny class you made there, quite twisted thx!

Kirby


On Thu, May 28, 2009 at 8:27 AM, Scott David
Daniels wrote:
> kirby urner wrote:
>>
>> ... Hey, did you know Ellipsis is a new primitive object in Python 3,
>> denoted ... ?
>>
> ...
>>
>> Ellipsis
>
> Actually, it has been around for quite a while.  Try this in even a much
> older Python:
>
>    >>> class Funny(object):
>            def __getitem__(self, *args):
>                return args
>    >>> Funny[1, ..., 10]
>    (1, Ellipsis, 3)
>    >>> Ellipsis
>    Ellipsis
>
> --Scott David Daniels
> scott.dani...@acm.org
>
> ___
> Edu-sig mailing list
> Edu-sig@python.org
> http://mail.python.org/mailman/listinfo/edu-sig
>
___
Edu-sig mailing list
Edu-sig@python.org
http://mail.python.org/mailman/listinfo/edu-sig


Re: [Edu-sig] poking around in Py3k (recycling old algebra)

2009-05-28 Thread kirby urner
On Wed, May 27, 2009 at 11:45 PM, kirby urner wrote:

<< SNIP >>

> Hey, I was just learning from David Beazley on Safari that __repr__ is
> generally supposed to emit a string that'll eval right back to the
> object represented.  So if I have Modulo type and go k = Modulo(10)
> then my __repr__ should maybe just emit 'Modulo(10)'.  __str__ is for
> something prettier maybe (adding makeup).
>

Speaking of David Beazley, not all published books about Python on
Safari are of equally high quality and David's seem among the best.

I was reading about descriptors, again per Holden workshop, and
noticing the author adding at class level, but never making use of the
passed instance argument, only self (inside the descriptor).

David, on the other hand, explicitly tells us not to instantiate
descriptors at the instance level (they're meant for the classdict)
but then shows using one to pass through to the instance __dict__,
using __set__ and __get__ to communicate at the instance level.

This is what one would expect of attributes as the "normal" case is
instance-level attributes (stuff in self.__dict__) and the first
advanced Python book I was reading demonstrated no awareness of that,
plus handed off to other writers in the case of needing some heavy
lifting (OK to do, but I thought this one, not by David, over did it).

He prepends a "_" to make sure the attribute name doesn't collide with
its own instance-level key in self.__dict__.

Here's some related material:

>>> class Codeguardian:
def __init__(self,codeword=None):
print("I am here master...")
self.default = 0
self.payme = 0
self.codeword = codeword

def __set__(self, instance, value):
print("I shall perform my duty...")
self.payme += 1
if (value == self.codeword or value in range(5)):
setattr(instance,"_thecode",value)
else:
print("the value was rejected, pah!")
def __get__(self, instance, klass):
print("I shall fetch ._thecode")
self.payme += 1
if "_thecode" not in instance.__dict__:
print("I have set it to 0 for you sir/mam!")
setattr(instance,"_thecode",0)
return instance._thecode


>>> class Castle:
def __init__(self, name):
self.name = name
# build castle real quick


>>> mycastle = Castle("Somewhere Special")
>>> mycastle.keeper = Codeguardian("hello kitty")
I am here master...
>>> myothercastle = Castle("Somewhere Less Special")
>>> myothercastle = Codeguardian("pssst!")
I am here master...
>>> mycastle.keeper = 4
>>> mycastle.keeper
4
>>> mycastle.__dict__
{'keeper': 4, 'name': 'Somewhere Special'}

OK, this isn't going according to plan at all.  Why?

Because I did what David said not to do and tried stuffing my
Codeguardian into an instance of Castle, rather than into the Castle
class itself.  Result, __getattribute__ and __setattr__ don't find my
Codeguardian when I go to set the "keep" attribute.

So let's try that again:

>>> Castle.keep = Codeguardian("hello kitty")
I am here master...
>>> mycastle = Castle("Somewhere Special")
>>> myothercastle = Castle("Somewhere Less Special")
>>> mycastle.keeper = 4
>>> mycastle.keep = "the crown jewels"
I shall perform my duty...
the value was rejected, pah!
>>> mycastle.keep = 4
I shall perform my duty...
>>> myothercastle.keep
I shall fetch ._thecode
I have set it to 0 for you sir/mam!
0
>>> myothercastle.__dict__
{'_thecode': 0, 'name': 'Somewhere Less Special'}
>>> mycastle.__dict__
{'keeper': 4, '_thecode': 4, 'name': 'Somewhere Special'}
>>>

OK, that worked, except I left in the goof where I set "keeper"
instead of "keep", cluttering my instance __dict__ with some worthless
DNA.  Or maybe that was intentional?

The point here is the Codeguardian works for the class, even if it has
a way to communicate with the instance at the time of setting and
getting.  In David's example, the instance __dict__ key is built by
prepending a "_" to a passed in variable name so the same Codeguardian
may be set to guard several unique attributes.**

I question here is how does Codeguardian get paid, since he's clearly
keeping an internal tally.  How do we get at the instance level
properties of Codeguardian?

First, note that there's nothing to prevent just poking a value for
_thecode directly into an instance:

>>> mycastle.__dict__["_thecode"]="hah, got around ya!"
>>> mycastle.__dict__
{'keeper': 4, '_thecode': 'hah, got around ya!', 'name': 'Somewhere Special'}
>>> mycastle.keep
I shall fetch ._thecode
'hah, got around ya!'

Anyway, recommended:

Python Essential Reference, Fourth Edition
By: David M. Beazley
Last Updated on Safari: 2009/04/30

Kirby

** David's example:

class TypedProperty(object):
def __init__(self,name,type,default=None):
 

Re: [Edu-sig] poking around in Py3k (recycling old algebra)

2009-05-28 Thread Scott David Daniels

kirby urner wrote:

... Hey, did you know Ellipsis is a new primitive object in Python 3, denoted 
... ?


...

Ellipsis


Actually, it has been around for quite a while.  Try this in even a much
older Python:

>>> class Funny(object):
def __getitem__(self, *args):
return args
>>> Funny[1, ..., 10]
(1, Ellipsis, 3)
>>> Ellipsis
Ellipsis

--Scott David Daniels
scott.dani...@acm.org

___
Edu-sig mailing list
Edu-sig@python.org
http://mail.python.org/mailman/listinfo/edu-sig


[Edu-sig] poking around in Py3k (recycling old algebra)

2009-05-27 Thread kirby urner
The code below is somewhat boringly similar to other stuff I've
archived here before, about finding all the totatives (defined below)
of some N, then multiplying all possible pairs (a Cartesian product)
modulo N to show how you've got closure i.e. you never get outside the
group.

The totatives of N are the numbers 1...(N-1) with no factors in common
with N.  If N is prime, every integer 1...(N-1) is a totative.  The
totient of N is *how many* totatives it has.  Think how it'd only take
you a few lessons to have your students impressing their guardians
with stuff Euler talked about (make sure they pronounce "Euler"
right).

Hey, did you know Ellipsis is a new primitive object in Python 3, denoted ... ?

>>> ...
Ellipsis

What's a little bit different in this pass is I'm applying some stuff
I learned from Steve Holden @ Pycon re iterators, other subsequent
trainings.

Iterators are "one way streets" that become exhausted (dead end in
StopIteration) so you might need to clone them ahead of time.

The itertools tee is good for that e.g.  lazyA, lazyB = itertools.tee(
iteratorX ) will give you two for the price of one, then don't use
iteratorX anymore (it's exhausted).

Below, I want the totient (== number of totatives), so consume a whole
iterator going totient = len(list(theiterator)) -- but fortunately I
tee first.

Hey, I was just learning from David Beazley on Safari that __repr__ is
generally supposed to emit a string that'll eval right back to the
object represented.  So if I have Modulo type and go k = Modulo(10)
then my __repr__ should maybe just emit 'Modulo(10)'.  __str__ is for
something prettier maybe (adding makeup).

itertools.product will pair each with every, given two iterators
(actually, takes any number, proceeds odometer style), but again, if
you were to use the same iterator twice, you'd end up consuming all
the rows so nothing left for columns or vice versa.

That's where the repeat keyword argument comes in, which I use as an
alternative to tee for a check (see multiply_a vs. multiply_b).

Other little known features of Python 3.x, the ability to write:

>>> def f(x:int) -> int:  return x * x

>>> f.__annotations__
{'x': , 'return': }

The new __prepare__ method allowing processing in the classdict you're
about to hand off to __new__, bolstering metaclass definitions.

Set and dictionary comprehensions, cool.

I play with a set comprehension below, limiting the output of the
Cayley table to unique terms only (note curly braces in output) --
what takes the most room are the powering tables, where I take each
totative t and go pow( t, e, N) with e ranging from 0 to totient-1 (a
list comprehension).  This relates to RSA.

Also this is kinda weird (newly legal syntax):

>>> alpha, *junk, omega = "This is sorta cool syntax eh?".split()
>>> alpha
'This'
>>> junk
['is', 'sorta', 'cool', 'syntax']
>>> omega
'eh?'
>>>

OK, the rest is source code, with output listed at the end...

"""
product does a cartesian product of two iterables
tee replicates iterables 'repeat' times (default repeat=2)

More of what this is actually about:

http://www.4dsolutions.net/ocn/flash/group.html
(yikes, evil noise!  turn down those headphones!)

"""

from itertools import product, tee

def gcd(a,b):
"""
EA per Guido
"""
while b:
a, b = b, a % b
return a

def tots(n):
"""
returns iterator of no factors
in common (totatives)
"""
return (i for i in range(n) if gcd(i, n) == 1)

def multiply_a(ts,n):
"""
Cayley Table of ts x ts modulo n
"""
ps = product(ts, repeat=2)
return (i*j % n for i,j in ps)

def multiply_b(ts,n):
"""
Cayley Table of ts x ts modulo n
(alternate implementation)
"""
row, col = tee(ts)
ps = product(row, col)
return (i*j % n for i,j in ps)

def powers(ts,n):
a,b = tee(ts)
totient = len(list(b))
for t in a:
print([pow(t,exp,n) for exp in range(totient)])

def test(n):
print({i for i in multiply_a(tots(n),n)})
# print({i for i in multiply_b(tots(n),n)})
powers(tots(n),n)

if __name__ == '__main__':
test(12)
test(15)
test(21)
test(24)

So what's the printout if you run it?

>>>  RESTART 
>>>
{1, 11, 5, 7}
[1, 1, 1, 1]
[1, 5, 1, 5]
[1, 7, 1, 7]
[1, 11, 1, 11]
{1, 2, 4, 7, 8, 11, 13, 14}
[1, 1, 1, 1, 1, 1, 1, 1]
[1, 2, 4, 8, 1, 2, 4, 8]
[1, 4, 1, 4, 1, 4, 1, 4]
[1, 7, 4, 13, 1, 7, 4, 13]
[1, 8, 4, 2, 1, 8, 4, 2]
[1, 11, 1, 11, 1, 11, 1, 11]
[1, 13, 4, 7, 1, 13, 4, 7]
[1, 14, 1, 14, 1, 14, 1, 14]
{1, 2, 4, 5, 8, 10, 11, 13, 16, 17, 19, 20}
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 2, 4, 8, 16, 11, 1, 2, 4, 8, 16, 11]
[1, 4, 16, 1, 4, 16, 1, 4, 16, 1, 4, 16]
[1, 5, 4, 20, 16, 17, 1, 5, 4, 20, 16, 17]
[1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8]
[1, 10, 16, 13, 4, 19, 1, 10, 16, 13, 4, 19]
[1, 11, 16, 8, 4, 2, 1, 11, 16, 8, 4, 2]
[1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13]
[1, 16, 4, 1, 16, 4, 1, 16, 4, 1, 16,