Re: new.instancemethod __iter__

2010-02-07 Thread Martin Drautzburg
Steven D'Aprano wrote:

 If you want iterator operations similar to itertools, why does this
 mean you need to replace anything? Just create your own iterators.
 
 Or use pre-processing and post-processing to get what you want.
 
 Can you show an example of what you would like to happen?

Steven, 

my classes repesent musical objects. The fundamental paradigm I want to
apply is that of a Sequence, i.e. the most abstract aspect of music is
that things occur in a certain order.

Then I have a TimedSequence class, which is a Sequences whose elements
have a time attribute. I now want to be able to append such Sequences
by writing

s1 = TimedSequence (time=1,'a') # one-element Sequence
s2 = TimedSequence (time=2,'b')

y = s1*2 + s2

Naively appending those sequences would give me
Time=1,'a'
Time=1,'a'
Time=2,'b'

but this is not what I want. Time needs to progress if I append a
sequence to another. So what I really want is something like

Time=1,'a'
Time=2,'a'
Time=3,'b'

This implies that time is shifted to the next integer, but this is not
always the case. I need to know about some kind of alignment. In
music this translates to let a sequence start at the beginning of a
bar, or half bar or quarter note or whatever.

So I want to write

y = s1*2 + s2(align=10)

which should iterate as

Time=1,'a'
Time=2,'a'
Time=10,'b'

I have no difficulty passing align to the object (using __call__) and
use it while I furnish my own __iter__() method. However I don't quite
see how I can do this with bare itertools, though I may be wrong here.

Bare in mind that it is not only about somehow getting the job done. The
beauty of the resulting syntax is also important.




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


Re: new.instancemethod __iter__

2010-02-07 Thread Martin Drautzburg
Christian Heimes wrote:


 If you *really* need to overwrite __iter__ on your instance rather
 than defining it on your class, you need to proxy the method call:
 
 class MyObject(object):
def __iter__(self):
   return self.myiter()
 
 obj = MyObject()
 obj.myiter = myiter
 
 That should do the trick.

Thanks a lot, that works.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: new.instancemethod __iter__

2010-02-07 Thread Steve Holden
Martin Drautzburg wrote:
 Steven D'Aprano wrote:
 
 If you want iterator operations similar to itertools, why does this
 mean you need to replace anything? Just create your own iterators.

 Or use pre-processing and post-processing to get what you want.

 Can you show an example of what you would like to happen?
 
 Steven, 
 
 my classes repesent musical objects. The fundamental paradigm I want to
 apply is that of a Sequence, i.e. the most abstract aspect of music is
 that things occur in a certain order.
 
 Then I have a TimedSequence class, which is a Sequences whose elements
 have a time attribute. I now want to be able to append such Sequences
 by writing
 
 s1 = TimedSequence (time=1,'a') # one-element Sequence
 s2 = TimedSequence (time=2,'b')
 
 y = s1*2 + s2
 
 Naively appending those sequences would give me
 Time=1,'a'
 Time=1,'a'
 Time=2,'b'
 
 but this is not what I want. Time needs to progress if I append a
 sequence to another. So what I really want is something like
 
 Time=1,'a'
 Time=2,'a'
 Time=3,'b'
 
 This implies that time is shifted to the next integer, but this is not
 always the case. I need to know about some kind of alignment. In
 music this translates to let a sequence start at the beginning of a
 bar, or half bar or quarter note or whatever.
 
 So I want to write
 
 y = s1*2 + s2(align=10)
 
 which should iterate as
 
 Time=1,'a'
 Time=2,'a'
 Time=10,'b'
 
 I have no difficulty passing align to the object (using __call__) and
 use it while I furnish my own __iter__() method. However I don't quite
 see how I can do this with bare itertools, though I may be wrong here.
 
 Bare in mind that it is not only about somehow getting the job done. The
 beauty of the resulting syntax is also important.
 
In that case why not just assume that the timing of a sequence is
relative to the current time unless the align argument is given?

You might also need an event of zero duration to set the start time for
a sequence.

regards
 Steve
-- 
Steve Holden   +1 571 484 6266   +1 800 494 3119
PyCon is coming! Atlanta, Feb 2010  http://us.pycon.org/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS:http://holdenweb.eventbrite.com/

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


Re: new.instancemethod __iter__

2010-02-07 Thread Martin Drautzburg
Steve Holden wrote:


 y = s1*2 + s2(align=10)
 
 which should iterate as
 
 Time=1,'a'
 Time=2,'a'
 Time=10,'b'
 
 I have no difficulty passing align to the object (using __call__)
 and use it while I furnish my own __iter__() method. However I don't
 quite see how I can do this with bare itertools, though I may be
 wrong here.
 
 Bare in mind that it is not only about somehow getting the job done.
 The beauty of the resulting syntax is also important.
 
 In that case why not just assume that the timing of a sequence is
 relative to the current time unless the align argument is given?

Well that's pretty much what I'm doing. I just fail to see how I can do
this with bare itertools. Currently I am doing it in the following way:

When I call a Sequence as in s2(align=2) I create a new Sequence where
the align value is simply stored in an instance variable. 

When creating the sum of two sequences, I create a Sequence with a new
iter() method which first iterates over self and then over the second
Sequence. But each time it has to look up the align value of the
respective sequence and adjust time accordingly. 

Appending the two Sequences is the easy part, but adjusting time is the
difficult part. My impression was, that itertools can only help to
solve the first part.

I may be missing something obvious. If that's the case, please let me
know.






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


Re: new.instancemethod __iter__

2010-02-07 Thread Steve Holden
Martin Drautzburg wrote:
 Steve Holden wrote:
 
 
 y = s1*2 + s2(align=10)

 which should iterate as

 Time=1,'a'
 Time=2,'a'
 Time=10,'b'

 I have no difficulty passing align to the object (using __call__)
 and use it while I furnish my own __iter__() method. However I don't
 quite see how I can do this with bare itertools, though I may be
 wrong here.

 Bare in mind that it is not only about somehow getting the job done.
 The beauty of the resulting syntax is also important.

 In that case why not just assume that the timing of a sequence is
 relative to the current time unless the align argument is given?
 
 Well that's pretty much what I'm doing. I just fail to see how I can do
 this with bare itertools. Currently I am doing it in the following way:
 
 When I call a Sequence as in s2(align=2) I create a new Sequence where
 the align value is simply stored in an instance variable. 
 
 When creating the sum of two sequences, I create a Sequence with a new
 iter() method which first iterates over self and then over the second
 Sequence. But each time it has to look up the align value of the
 respective sequence and adjust time accordingly. 
 
 Appending the two Sequences is the easy part, but adjusting time is the
 difficult part. My impression was, that itertools can only help to
 solve the first part.
 
 I may be missing something obvious. If that's the case, please let me
 know.
 
Perhaps I am assuming too much of your simulation environment/player.

I presumed that there would be a global current time value that would
be passed into or available to the play method of the sequences. However
I can see that you might need something more complex if (e.g.) you want
to be able to start playing at an arbitrary point in time.

regards
 Steve
-- 
Steve Holden   +1 571 484 6266   +1 800 494 3119
PyCon is coming! Atlanta, Feb 2010  http://us.pycon.org/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS:http://holdenweb.eventbrite.com/
-- 
http://mail.python.org/mailman/listinfo/python-list


new.instancemethod __iter__

2010-02-06 Thread Martin Drautzburg
Hello all

When I create an Object and set its __iter__ method from outside

s = Sequence #one of my own classes
s.__iter__ = new.instancemethod(f,s,Sequence)

I get different results, depending on whether I call


for x in y.__iter__():
print x

or

for x in y:
print x

The first case does what I expected, i.e. it iterates over whatever f()
yields. In the second case nothing is printed. I have the impression
that it still calls the original __iter__() method (the one defined at
the class level).

Why is that so?
How can I replace the __iter__() method so it does what I want.

The reason I want to do such things is I need to implement operations
similar to what itertools do. However I want my own classes and the
operations are only similar to itertools, but differ in significant
details.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: new.instancemethod __iter__

2010-02-06 Thread Steven D'Aprano
On Sat, 06 Feb 2010 23:53:53 +0100, Martin Drautzburg wrote:

 Hello all
 
 When I create an Object and set its __iter__ method from outside
 
 s = Sequence #one of my own classes
 s.__iter__ = new.instancemethod(f,s,Sequence)

I'm confused as to why you are aliasing your class before changing it. 
The above just makes s an alternative name for Sequence.

Did you mean this?

s = Sequence() # make an instance of the class


 I get different results, depending on whether I call
 
 
 for x in y.__iter__():
 print x

What's y? Where does it come from? Is y supposed to be an instance of 
Sequence?


 or
 
 for x in y:
 print x
 
 The first case does what I expected, i.e. it iterates over whatever f()
 yields. In the second case nothing is printed. I have the impression
 that it still calls the original __iter__() method (the one defined at
 the class level).

Yes, that's almost certainly what is happening. As an optimization, 
Python bypasses the instance for special methods __NAME__.


 Why is that so?
 How can I replace the __iter__() method so it does what I want.

The best solution is, find another way to do what you want.

The clunky solution is to use delegation to wrap your class, and have the 
outer class re-direct calls to special methods to the instance first.

 
 The reason I want to do such things is I need to implement operations
 similar to what itertools do. However I want my own classes and the
 operations are only similar to itertools, but differ in significant
 details.

I don't understand this.

If you want iterator operations similar to itertools, why does this 
mean you need to replace anything? Just create your own iterators.

Or use pre-processing and post-processing to get what you want.

Can you show an example of what you would like to happen?



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


Re: new.instancemethod __iter__

2010-02-06 Thread Christian Heimes
Martin Drautzburg wrote:
 The first case does what I expected, i.e. it iterates over whatever f()
 yields. In the second case nothing is printed. I have the impression
 that it still calls the original __iter__() method (the one defined at
 the class level).

 Why is that so?
 How can I replace the __iter__() method so it does what I want.

Virtually all __magic__ methods are looked up on the type, not the
instance. So obj.__iter__() translates into type(obj).__iter__(obj).

If you *really* need to overwrite __iter__ on your instance rather than
defining it on your class, you need to proxy the method call:

class MyObject(object):
   def __iter__(self):
  return self.myiter()

obj = MyObject()
obj.myiter = myiter

That should do the trick.

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