Re: Why is recursion so slow?

2008-07-01 Thread Rich Harkins

Nick Craig-Wood wrote:
[snip]

By definition any function in a functional language will
always produce the same result if given the same arguments, so you can
memoize any function.



Ah, so that's why time.time() seems to be stuck...  ;)

Rich

--
http://mail.python.org/mailman/listinfo/python-list


Re: opposite of zip()?

2007-12-17 Thread Rich Harkins
[EMAIL PROTECTED] wrote:
 Given a bunch of arrays, if I want to create tuples, there is
 zip(arrays). What if I want to do the opposite: break a tuple up and
 append the values to given arrays:
map(append, arrays, tupl)
 except there is no unbound append() (List.append() does not exist,
 right?).
 

list.append does exist (try the lower-case flavor).

 Without append(), I am forced to write a (slow) explicit loop:
   for (a, v) in zip(arrays, tupl):
   a.append(v)
 

Except that isn't technically the opposite of zip.  The opposite would
be a tuple of single-dimensional tuples:

def unzip(zipped):

Given a sequence of size-sized sequences, produce a tuple of tuples
that represent each index within the zipped object.

Example:
 zipped = zip((1, 2, 3), (4, 5, 6))
 zipped
[(1, 4), (2, 5), (3, 6)]
 unzip(zipped)
((1, 2, 3), (4, 5, 6))

if len(zipped)  1:
raise ValueError, 'At least one item is required for unzip.'
indices = range(len(zipped[0]))
return tuple(tuple(pair[index] for pair in zipped)
 for index in indices)

This is probably not the most efficient hunk of code for this but this
would seem to be the correct behavior for the opposite of zip and it
should scale well.

Modifying the above with list.extend would produce a variant closer to
what I think you're asking for:

def unzip_extend(dests, zipped):

Appends the unzip versions of zipped into dests.  This avoids an
unnecessary allocation.

Example:
 zipped = zip((1, 2, 3), (4, 5, 6))
 zipped
[(1, 4), (2, 5), (3, 6)]
 dests = [[], []]
 unzip_extend(dests, zipped)
 dests
[[1, 2, 3], [4, 5, 6]]

if len(zipped)  1:
raise ValueError, 'At least one item is required for unzip.'
for index in range(len(zipped[0])):
dests[index].extend(pair[index] for pair in zipped)

This should perform pretty well, as extend with a comprehension is
pretty fast.  Not that it's truly meaningful, here's timeit on my 2GHz
laptop:

bash-3.1$ python -m timeit -s 'import unzip; zipped=zip(range(1024),
range(1024))' 'unzip.unzip_extend([[], []], zipped)'
1000 loops, best of 3: 510 usec per loop

By comparison, here's the unzip() version above:

bash-3.1$ python -m timeit -s 'import unzip; zipped=zip(range(1024),
range(1024))' 'unzip.unzip(zipped)'
1000 loops, best of 3: 504 usec per loop

Rich

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: opposite of zip()?

2007-12-17 Thread Rich Harkins
Matt Nordhoff wrote:
[snip]

 
 As Paddy wrote, zip is its own unzip:
 
 zipped = zip((1, 2, 3), (4, 5, 6))
 zipped
 [(1, 4), (2, 5), (3, 6)]
 unzipped = zip(*zipped)
 unzipped
 [(1, 2, 3), (4, 5, 6)]
 
 Neat and completely confusing, huh? :-)
 
 http://paddy3118.blogspot.com/2007/02/unzip-un-needed-in-python.html

I hadn't thought about zip() being symmetrical like that.  Very cool...

Rich
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Descriptors and side effects

2007-11-05 Thread Rich Harkins
[EMAIL PROTECTED] wrote:
 Hello everyone,
 
 I'm trying to do seemingly trivial thing with descriptors: have
 another attribute updated on dot access in object defined using
 descriptors.

[snip]

 A setter function should have updated self.l just like it updated
 self.s:
 
   def __set__(self, obj, val):
   self.s=val
   self.l=len(val)
   print setting value:, self.s, length:, self.l
 
 Yet it didn't happen.
 
[snip]

I noticed that Python will block all attribute overrides (either via
__dict__ through setattr) if the property has a __set__ method.  The
standard property has this method and there is no way that I can find to
defeat it.  So, here is what I use:

class ConstProperty(object):

Provides a property that keeps its return value.  The function will
only be called on the first access.  After that the same value can
be used over and over again with no function call penalty.  If the
cached value needs to be cleared, simply del the attribute.

 class MyClass(object):
... def __init__(self, x):
... self.x = x
... @ConstProperty
... def y(self):
... print HERE
... return self.x ** 2
...
 obj = MyClass(5)
 obj.y
HERE
25
 obj.y
25


def __init__(self, fn):
self.fn = fn

def __get__(self, target, cls=None):
if target is None:
return self.fn  # Helps pydoc
else:
obj = self.fn(target)
setattr(target, self.fn.__name__, obj)
return obj

This is a little different than what you originally posted, but
hopefully it is close enough to be helpful.

Cheers!
Rich

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Descriptors and side effects

2007-11-05 Thread Rich Harkins
Bruno Desthuilliers wrote:
[snip]
 I'm sorry, but this looks like a very complicated way to do a simple thing:
 
 class MySimpleClass(object):
def __init__(self, x):
  self.x = x
  self.y = x ** 2
 
 

Sure, for the absurdly simplified case I posed as an example.  ;)

Here's another:

class Path(tuple):
@ConstProperty
def pathstr(self):
print DEBUG: Generating string
return '/'.join(self)

def __add__(self, other):
if isinstance(other, tuple):
 return Path(tuple.__add__(self, other))
else:
 return Path(tuple.__add__(self, (other,)))

 ROOT = Path(())
 path = ROOT + 'x' + 'y' + 'z'
 path.pathstr
DEBUG: Generating string
/x/y/z
 path.pathstr
/x/y/z

Basically, you can use ConstProperty above for items you don't want to
calculate automatically, but only when someone actually WANTS it.  After
it is applied, then the penalties for function call of the property and
the computation are wiped out once the second access is requested.

Now, in the original example, len() might be considered too little for
this use and should be just generated in the constructor for free.
OTOH, that assumes that __len__ hasn't been overridden to do something
more complicated and time consuming.  If the antecedent object is
static, and the derivative consequent is also static, then ConstProperty
works very well and shouldn't cost more on the first access than any
other built-in property function.

BTW, another use is to avoid creating lots of unnecessary objects for
free unless they are accessed.  Another quickie example:

class Node(object):
hasChildList = False
hasAttributesDict = False

@ConstProperty
def children(self):
self.hasChildList = True
return []

@ConstProperty
def attributes(self):
self.hasAttributesDict = True
return {}

The extra class/object attributes can be used to test for whether the
associated objects were created.  When used in a large tree, not
creating a lot of extra lists and dictionaries can save a lot of memory
and CPU as the children and attributes are not created or explored
unless they were manipulated.

Rich
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Descriptors and side effects

2007-11-05 Thread Rich Harkins
Bruno Desthuilliers wrote:
 Rich Harkins a écrit :
 [EMAIL PROTECTED] wrote:
 Hello everyone,

 I'm trying to do seemingly trivial thing with descriptors: have
 another attribute updated on dot access in object defined using
 descriptors.
 [snip]

 A setter function should have updated self.l just like it updated
 self.s:

 def __set__(self, obj, val):
 self.s=val
 self.l=len(val)
 print setting value:, self.s, length:, self.l

 Yet it didn't happen.

 [snip]

 I noticed that Python will block all attribute overrides (either via
 __dict__ through setattr) if the property has a __set__ method. 
 
 It doesn't block, it controls access to... Of course, if the __set__ 
 method is a no-op, then nothing will happen.
 
 The
 standard property has this method and there is no way that I can find to
 defeat it.
 
 defeat ? Why don't you just pass the appropriate fset function to 
 property ?
 
  So, here is what I use:

 class ConstProperty(object):
 
 Provides a property that keeps its return value.  The function will
 only be called on the first access.  After that the same value can
 be used over and over again with no function call penalty.  If the
 cached value needs to be cleared, simply del the attribute.

  class MyClass(object):
 ... def __init__(self, x):
 ... self.x = x
 ... @ConstProperty
 ... def y(self):
 ... print HERE
 ... return self.x ** 2
 ...
  obj = MyClass(5)
  obj.y
 HERE
 25
  obj.y
 25
 

 def __init__(self, fn):
 self.fn = fn

 def __get__(self, target, cls=None):
 if target is None:
 return self.fn   # Helps pydoc
 else:
 obj = self.fn(target)
 setattr(target, self.fn.__name__, obj)
 return obj
 
 
 
   m = MyClass(5)
   m.__dict__
 {'x': 5}
   m.y
 HERE
 25
   m.__dict__
 {'y': 25, 'x': 5}
   m.x = 42
   m.y
 25
   m.__dict__
 {'y': 25, 'x': 42}
  
 
 
 I'm sorry, but this looks like a very complicated way to do a simple thing:
 
 class MySimpleClass(object):
def __init__(self, x):
  self.x = x
  self.y = x ** 2
 
 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Functions as Objects, and persisting values

2007-11-05 Thread Rich Harkins
[snip]
 The thing you observe here is a called a closure. It consists of the 
 local variables surrounding e. So as long as you keep a reference to e, 
 you keep one to the variables of d itself.
 
 Diez

More specifically though it keeps references to the requested variables
only:


def closed():
x = global_x
y = Y_VAR
def inner():
return y
return inner

class Destroyable(object):
def __del__(self):
print DESTROYED

global_x = Destroyable()
inner = closed()
print inner()
del global_x
print inner()
print HERE

You will get:

Y_VAR
DESTROYED
Y_VAR
HERE

If the entire dict of closed() was kept you would have seen:

Y_VAR
Y_VAR
HERE
DESTROYED

Since closed hadn't been destroyed yet: thus there was only one
reference remaining to global_x after closed() and inner() were called.

Rich

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Descriptors and side effects

2007-11-05 Thread Rich Harkins
Bruno Desthuilliers wrote:
 Which is easy to do with properties too.

True enough.  It's the caching of the return value that's the value add
of course.  ;)

 
  After
 it is applied, then the penalties for function call of the property and
 the computation are wiped out once the second access is requested.
 
 Agreed. But I wouldn't use such a scheme for mutable types - which are 
 still the common case.
 

In many cases, yeah.  Though I use a lot of immutable stuff in some of
my pet projects and such.  ConstProperty is definitely not meant as a
replacement for property, only when something constant can be derived
from something else constant, especially when the derivation is expensive.

 Now, in the original example, len() might be considered too little for
 this use and should be just generated in the constructor for free.
 OTOH, that assumes that __len__ hasn't been overridden to do something
 more complicated and time consuming.  If the antecedent object is
 static, and the derivative consequent is also static,
 
 You mean 'immutable', I assume...

Yeah, that's probably the better term.

[snip]

Again, I've used it quite a bit for various things and it's worked well
for the sort of thing the OP was requesting.  Of course, your mileage
may vary.  :)

Cheers!
Rich

PS: Sorry about the weird reposts.  Thunderbird chaos.

-- 
http://mail.python.org/mailman/listinfo/python-list