473,320 Members | 1,896 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

trouble with generators

Hi Pythonistas,

I'm stuck in a maze of new style classes and generators. While I love the
concepts, I obviously didn't grok them throughout.

I'm trying to generate a bunch of similar classes, where some are contained
in list attributes of others, e.g.:

class A:
def __init__(self):
self.id = 'A1'
self.b = [instances of B]

class B:
def __init__(self):
self.id = 'B1'

Here's the test code, I have:

#!/usr/bin/env python
# -*- coding: utf8 -*-

class A(object):
"A"
def __init__(self):
self.id = None
self.b = []

class B(object):
"B"
def __init__(self):
self.id = None

class Gen(object):
def records(self, cls):
for i in range(3):
setattr(cls, "id", "%s%s" % (cls.__doc__, i))
yield cls

def display(self, rec):
for i in rec.__dict__.keys():
if not i.startswith("_"):
print "%s: %s: %s" % (rec.__doc__, i, rec.__dict__[i])

class GenA(Gen):
def __init__(self):
self.genB = GenB()

def records(self):
for a in Gen.records(self, A()):
for b in self.genB.records():
#self.genB.display(b)
a.b.append(b)
#self.display(a)
yield a

class GenB(Gen):
def records(self):
return Gen.records(self, B())

# testing..

aRecs = []
bRecs = []

for i, r in enumerate(GenB().records()):
bRecs.append(r)
print i, r.id, r

for i, r in enumerate(GenA().records()):
aRecs.append(r)
print i, r.id, r
for b in r.b:
print b.id, b
Here's the commented output:
# even if I keep a reference to each rec, the object is reused:
0 B0 <__main__.B object at 0xb7bd0f8c>
1 B1 <__main__.B object at 0xb7bd0f8c>
2 B2 <__main__.B object at 0xb7bd0f8c>
# same here, with additional quadratic behavior, I do not understand
0 A0 <__main__.A object at 0xb7bd206c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
1 A1 <__main__.A object at 0xb7bd206c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd20ec>
B2 <__main__.B object at 0xb7bd20ec>
B2 <__main__.B object at 0xb7bd20ec>
2 A2 <__main__.A object at 0xb7bd206c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd20ec>
B2 <__main__.B object at 0xb7bd20ec>
B2 <__main__.B object at 0xb7bd20ec>
B2 <__main__.B object at 0xb7bd0f8c>
B2 <__main__.B object at 0xb7bd0f8c>
B2 <__main__.B object at 0xb7bd0f8c>

I expected to get 3 different class objects from both sections, with each A
containing 3 different Bs in the latter section, but obviously got
something else.

Could some kind soul help me to distangle my mind twist here? Am I healable?

TIA, Pete
May 10 '07 #1
4 1089
Hans-Peter Jansen schrieb:
Hi Pythonistas,

I'm stuck in a maze of new style classes and generators. While I love the
concepts, I obviously didn't grok them throughout.

I'm trying to generate a bunch of similar classes, where some are contained
in list attributes of others, e.g.:
All your code below shows that you don't create classes, but _instances_
of classes. So - is that what you mean to do? Or do you really want to
create classes?
class A:
def __init__(self):
self.id = 'A1'
self.b = [instances of B]

class B:
def __init__(self):
self.id = 'B1'

Here's the test code, I have:

#!/usr/bin/env python
# -*- coding: utf8 -*-

class A(object):
"A"
def __init__(self):
self.id = None
self.b = []

class B(object):
"B"
def __init__(self):
self.id = None

class Gen(object):
def records(self, cls):
for i in range(3):
setattr(cls, "id", "%s%s" % (cls.__doc__, i))
yield cls

def display(self, rec):
for i in rec.__dict__.keys():
if not i.startswith("_"):
print "%s: %s: %s" % (rec.__doc__, i, rec.__dict__[i])

class GenA(Gen):
def __init__(self):
self.genB = GenB()

def records(self):
for a in Gen.records(self, A()):
Here you pass an instance of A, not the class A.
for b in self.genB.records():
#self.genB.display(b)
a.b.append(b)
#self.display(a)
yield a

class GenB(Gen):
def records(self):
return Gen.records(self, B())
Same here - instance of B.
# testing..

aRecs = []
bRecs = []

for i, r in enumerate(GenB().records()):
bRecs.append(r)
print i, r.id, r

for i, r in enumerate(GenA().records()):
aRecs.append(r)
print i, r.id, r
for b in r.b:
print b.id, b
Here's the commented output:
# even if I keep a reference to each rec, the object is reused:
0 B0 <__main__.B object at 0xb7bd0f8c>
1 B1 <__main__.B object at 0xb7bd0f8c>
2 B2 <__main__.B object at 0xb7bd0f8c>
Sure - because you create one B-instance, and pass that to your generator.

That generator then simply sets the succinct id's on that object, and
returns it. But it is always the same instance!!

In a nutshell, you do this:

b = B()
res = []
for i in xrange(3):
b.id = i
res.append(b)

Always the same b.

What you seem to want is this
>>class B(object):
.... pass
....
>>res = []
for i in xrange(3):
.... class BSubClass(B):
.... pass
.... BSubClass.id = i
.... res.append(BSubClass)
....
>>print [c.id for c in res]
[0, 1, 2]
>>>

# same here, with additional quadratic behavior, I do not understand
0 A0 <__main__.A object at 0xb7bd206c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
1 A1 <__main__.A object at 0xb7bd206c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd20ec>
B2 <__main__.B object at 0xb7bd20ec>
B2 <__main__.B object at 0xb7bd20ec>
2 A2 <__main__.A object at 0xb7bd206c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd210c>
B2 <__main__.B object at 0xb7bd20ec>
B2 <__main__.B object at 0xb7bd20ec>
B2 <__main__.B object at 0xb7bd20ec>
B2 <__main__.B object at 0xb7bd0f8c>
B2 <__main__.B object at 0xb7bd0f8c>
B2 <__main__.B object at 0xb7bd0f8c>

It's not quadratic - you add the same B to a.b in each generator run, so
the first run shows 3 times the B, then 6, then 9. And because its
always the same instance, printing them yields the same id for all - B2.
I expected to get 3 different class objects from both sections, with each A
containing 3 different Bs in the latter section, but obviously got
something else.

Could some kind soul help me to distangle my mind twist here? Am I healable?
I'm still not sure what you want - do you want instances created, or
classes? For the former, you need constructor calls on your classes, and
pass the class instead of an instance. Like this:
class B(object):
pass
def g(cls):
for i in xrange(3):
o = cls()
o.id = i
yield o

list(g(B))

Or you want really different classes (which is somewhat strange then to
create that hierarchy of yours with As containing Bs), which you can
accomplish using a class-statement in the generator as shown above.
There are other ways as well, but less intuitive I'd say.
Maybe stepping back and telling us what you want to accomplish here
would help

Diez

May 10 '07 #2
In <f1*************@news.t-online.com>, Hans-Peter Jansen wrote:
class Gen(object):
def records(self, cls):
for i in range(3):
setattr(cls, "id", "%s%s" % (cls.__doc__, i))
yield cls

[…]

class GenA(Gen):
def __init__(self):
self.genB = GenB()

def records(self):
for a in Gen.records(self, A()):
Here you create an instance of `A` and pass that *instance* and not the
*class*. If you would pass the class here, you must create objects in
`Gen.records()`.

Ciao,
Marc 'BlackJack' Rintsch
May 10 '07 #3
Hi Diez,

first, thanks for your comprehensive answer.

Diez B. Roggisch wrote:
Hans-Peter Jansen schrieb:
>>
I'm trying to generate a bunch of similar classes, where some are
contained in list attributes of others, e.g.:

All your code below shows that you don't create classes, but _instances_
of classes. So - is that what you mean to do?
Yes, exactly. Sorry for the confusion..
>
In a nutshell, you do this:

b = B()
res = []
for i in xrange(3):
b.id = i
res.append(b)

Always the same b.

What you seem to want is this
>>class B(object):
... pass
...
>>res = []
>>for i in xrange(3):
... class BSubClass(B):
... pass
... BSubClass.id = i
... res.append(BSubClass)
...
>>print [c.id for c in res]
[0, 1, 2]

I'm still not sure what you want - do you want instances created, or
classes? For the former, you need constructor calls on your classes, and
pass the class instead of an instance. Like this:
class B(object):
pass
def g(cls):
for i in xrange(3):
o = cls()
o.id = i
yield o

list(g(B))
Yes, that did the trick. Silly me. Rookie error. Here's what I was after:

#!/usr/bin/env python
# -*- coding: utf8 -*-

class A(object):
"A"
def __init__(self):
self.id = None
self.b = []

class B(object):
"B"
def __init__(self):
self.id = None

class Gen(object):
"Gen"
def records(self, cls):
for n in range(3):
i = cls()
i.id = "%s%s" % (i.__doc__, n)
yield i

class GenA(Gen):
def __init__(self):
self.genB = GenB()

def records(self):
for a in Gen.records(self, A):
for b in self.genB.records():
a.b.append(b)
yield a

class GenB(Gen):
def records(self):
return Gen.records(self, B)

aRecs = []
bRecs = []

for i, r in enumerate(GenB().records()):
bRecs.append(r)
print i, r.id, r

for i, r in enumerate(GenA().records()):
aRecs.append(r)
print i, r.id, r
for b in r.b:
print b.id, b

created pretty nice different _instances_ of what I wanted:
0 B0 <__main__.B object at 0xb7cacfec>
1 B1 <__main__.B object at 0xb7cae04c>
2 B2 <__main__.B object at 0xb7cae08c>

0 A0 <__main__.A object at 0xb7cae12c>
B0 <__main__.B object at 0xb7cae1ac>
B1 <__main__.B object at 0xb7cae1ec>
B2 <__main__.B object at 0xb7cae22c>
1 A1 <__main__.A object at 0xb7cae16c>
B0 <__main__.B object at 0xb7cae2ac>
B1 <__main__.B object at 0xb7cae2ec>
B2 <__main__.B object at 0xb7cae32c>
2 A2 <__main__.A object at 0xb7cae26c>
B0 <__main__.B object at 0xb7cae3ac>
B1 <__main__.B object at 0xb7cae3ec>
B2 <__main__.B object at 0xb7cae42c>

Didn't found the forest because all the trees. Thanks again.

Greetings to Berlin,
Pete
May 10 '07 #4
Marc 'BlackJack' Rintsch wrote:
In <f1*************@news.t-online.com>, Hans-Peter Jansen wrote:
>class Gen(object):
def records(self, cls):
for i in range(3):
setattr(cls, "id", "%s%s" % (cls.__doc__, i))
yield cls

[…]

class GenA(Gen):
def __init__(self):
self.genB = GenB()

def records(self):
for a in Gen.records(self, A()):

Here you create an instance of `A` and pass that *instance* and not the
*class*. If you would pass the class here, you must create objects in
`Gen.records()`.
Yes, that was my fault, as you both found.
Ciao,
Marc 'BlackJack' Rintsch
Thanks, Marc.

Cheers, Pete
May 10 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

23
by: Francis Avila | last post by:
Below is an implementation a 'flattening' recursive generator (take a nested iterator and remove all its nesting). Is this possibly general and useful enough to be included in itertools? (I know...
9
by: Francis Avila | last post by:
A little annoyed one day that I couldn't use the statefulness of generators as "resumable functions", I came across Hettinger's PEP 288 (http://www.python.org/peps/pep-0288.html, still listed as...
8
by: Timothy Fitz | last post by:
It seems to me that in python, generators are not truly coroutines. I do not understand why. What I see is that generators are used almost exclusively for generation of lists just-in-time. Side...
3
by: Carlos Ribeiro | last post by:
As a side track of my latest investigations, I began to rely heavily on generators for some stuff where I would previsouly use a more conventional approach. Whenever I need to process a list, I'm...
5
by: Robert Oschler | last post by:
Preamble: - I know this is the Python forum - I know about (and have used) Jython I already posted this question in comp.lang.java. But after a week I have still not received a single reply....
15
by: Jordan Rastrick | last post by:
First, a disclaimer. I am a second year Maths and Computer Science undergraduate, and this is my first time ever on Usenet (I guess I'm part of the http generation). On top of that, I have been...
3
by: Michael Sparks | last post by:
Hi, I'm posting a link to this since I hope it's of interest to people here :) I've written up the talk I gave at ACCU Python UK on the Kamaelia Framework, and it's been published as a BBC...
6
by: Talin | last post by:
I've been using generators to implement backtracking search for a while now. Unfortunately, my code is large and complex enough (doing unification on math expressions) that its hard to post a...
13
by: Martin Sand Christensen | last post by:
Hi! First a bit of context. Yesterday I spent a lot of time debugging the following method in a rather slim database abstraction layer we've developed: ,---- | def selectColumn(self,...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.