Re: Self reordering list in Python

2005-09-27 Thread ABO
LRU caches are nice and simple, but if you want something fancier, with
support for squid-like expiry models (ie, using mtime and atime to
estimate a "stale time", and IMS fetches), you can have a look at my
GCache;

http://minkirri.apana.org.au/~abo/projects/GCache

Even if you don't want something that fancy, it uses a PQueue priority
queue to achieve exactly what you want. I provide a pure-python
implementation using bisect, but recommend a C extension module with
the same name by Andrew Snare which uses a fibonacci heap
(python-pqueue is the Debian Package).

Note that python 2.3 introduced a heapq module that does for queue
lists what bisect does for heap lists. I am planning to modify my
PQueue to use it instead of bisect.

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


Re: Self reordering list in Python

2005-09-27 Thread ABO
Actually, after posting this I did some more work on the PQueue modules
I had, implementing both bisect and heapq versions. It turns out the
bisect version is heaps faster if you ever delete or re-set values in
the queue.

The problem is heapq is O(N) for finding a particular entry in the
Queue, and any time you change or remove something from it you need to
heapify it again, which is also O(N).

Andew Snare has a C PQueue extension module that is heaps faster from
all angles. It uses a fibonacci heap and gets O(lg N) deletes and
re-sets. I think it does this by using the dict to speed finding
entries it in the heap, and uses some properties of the heap to "assign
lower" efficiently.

The queue used in the lrucache will also suffer from the O(N) problem
when deleting or reseting values in the cache.

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


Re: Life of Python

2005-06-30 Thread ABO
> Okay. This makes sense if the software is:
>
> 1) Designed by one institution.
> 2) Designed almost entirely before deployment.
> 3) Not designed to be worked on by users and
> semi-trained developers.
>
> In other words --- proprietary software.

In my experience, it doesn't work well even in these cases. Investing a
huge amount of effort designing in detail well in advance is nearly
always a mistake, unless the requirements are fully understood and
static... ie never.

Mostly the requirements are unknown until the (possibly internal)
customer has something. Nothing identifies requirements better than
deployment. Particularly with large projects that have long development
times, even if the requirements are well understood at the start, they
will have changed by the time it is deployed.

The biggest and most common mistake with software development is
believing that it finishes. Software has a lifecycle, and development
is like food; it is constantly required, otherwise the software dies.

--
Donovan Baarda

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


Re: Magic Optimisation

2005-09-14 Thread ABO
Bengt Richter wrote:
> On 5 Sep 2005 07:27:41 -0700, "Paul McGuire" <[EMAIL PROTECTED]> wrote:
>
> >I still think there are savings to be had by looping inside the
> >try-except block, which avoids many setup/teardown exception handling
> >steps.  This is not so pretty in another way (repeated while on
> >check()), but I would be interested in your timings w.r.t. your current
[...]
> Why not let popleft trigger an exception out of while True instead,
> and prevent tasks from raising StopIteration, and let them yield a None
> to indicate keep scheduling with no special action, and something else
[...]

The rule of thumb with exceptions is use them for infrequent events. If
you keep to this you end up with clean and fast code.

Provided task.next() raises StopIteration less than about 25% of the
time it is called, it is cleaner and more efficient to use an exception
than to return None. It is also more efficient to handle terminating by
allowing popleft trigger an exception. Try the following;

def loop(self):
self_call_exit_funcs = self.call_exit_funcs
self_pool_popleft = self.pool.popleft
self_pool_append = self.pool.append
while True:
try:
task = self_pool_popleft()
task.next()
self_pool_append(task)
except StopIteration:
self_call_exit_funcs(task)
except IndexError:
break

There are other "optimisations" that could be applied that make this
code faster but uglier. For example, putting another "while True: loop
inside the try block to avoid the try block setup each iteration. Also,
exception handling is slower when you specify the exception class (it
has to check if the exception matches), so you might be able to arrange
this with an anonymous accept: block around the task.next() to handle
the StopIteration exception.

Another thing that disturbs me is the popfirst/append every iteration.
Depending on how many loops through all the tasks before one
"finishes", you might find it more efficient to do this;

def loop(self):
self_pool = self.pool
self_pool_remove = self_pool.remove
self_call_exit_funcs = self.call_exit_funcs
while self_pool:
try:
for task in self_pool:
task.next()
except:
self_pool_remove(task)
self_call_exit_funcs(task)

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


Re: class attribute confusion

2010-12-04 Thread Omar Abo-Namous

Am 03.12.2010 23:11, schrieb Arnaud Delobelle:

OAN  writes:


Hi,

i was having a problem with class attributes initiated outside of
__init__. This code is a demonstration of what i mean:

class A():
 mylist = []
 def __init__(self):
 self.mylist.append(1)
 pass

class B(A):
 def __init__(self):
 A.__init__(self)
 self.mylist.append(2)

v = A()
print 'v:',v.mylist
x = B()
print 'x:',x.mylist
y = B()
print 'y:',y.mylist
z = A()
print 'z:',z.mylist
print 'v:',v.mylist

I would expect the following result:

v: [1]
x: [1, 2]
y: [1, 2]
z: [1]
v: [1]

Who wouldn't, right? But actually python 2.6(.6) gives me the
following result:

v: [1]
x: [1, 1, 2]
y: [1, 1, 2, 1, 2]
z: [1, 1, 2, 1, 2, 1]
v: [1, 1, 2, 1, 2, 1]

The four variables v,x,y and z now actually share the same 'mylist'!!
To get the correct results, i have to initialize 'mylist' inside of
the __init__ method!

Yes.  See below.


I think this behaviour is totally wrong, since it seems
A.__init__(self) is changing the value inside of A() not inside of the
object variable 'self' (that should be x or y)!!

It's not wrong at all.  You expect "mylist" to behave as an instance
attribute, but you defined it as a class attribute.  Instance attributes
are naturally initialised in the __init__() method.


Could you please point me to a reference in the doc??

Thanks in advance.


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