new.instancemethod __iter__

  • Thread starter Martin Drautzburg
  • Start date
M

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.
 
S

Steven D'Aprano

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?
 
M

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.
 
M

Martin Drautzburg

Steven said:
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.
 
S

Steve Holden

Martin said:
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
 
M

Martin Drautzburg

Steve Holden wrote:

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.
 
S

Steve Holden

Martin said:
Steve Holden wrote:



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
 
S

Steve Holden

Martin said:
Steve Holden wrote:



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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top