count strangeness

J

James Stroud

tal 65% python2.7
Python 2.7.1 (r271:86832, May 21 2011, 22:52:14)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
py> class C(object):
.... def __init__(self):
.... self.data = []
.... def doit(self, count=0):
.... for c in self.data:
.... count += c.doit(count)
.... count += 1
.... print count
.... return count
....
py> c = C()
py> c.data.extend([C() for i in xrange(10)])
py> c.doit()
1
2
4
8
16
32
64
128
256
512
1024
1024



WTF?


James
 
C

Chris Rebert

tal 65% python2.7
Python 2.7.1 (r271:86832, May 21 2011, 22:52:14)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
py> class C(object):
...   def __init__(self):
...     self.data = []
...   def doit(self, count=0):
...     for c in self.data:
...       count += c.doit(count)
...     count += 1
...     print count
...     return count
...
py> c = C()
py> c.data.extend([C() for i in xrange(10)])
py> c.doit()
1
2
4
8
16
32
64
128
256
512
1024
1024

WTF?

Assuming your question is "Why is 1024 there twice?", the answer is
that it was the return value of the initial c.doit() call, and the
interactive interpreter outputs all non-None expression results; for
example:
[In the Python REPL]
So, you explicitly print the 1024 in your function once, and the
interpreter implicitly outputs it the second time. Notice what happens
when we use a statement instead of an expression:
1
2
4
8
16
32
64
128
256
512
1024

And if we comment out the `print` in C.doit() and run your example again:
c = C()
c.data = [C() for i in xrange(10)]
c.doit() 1024

Cheers,
Chris
 
P

Peter Otten

James said:
tal 65% python2.7
Python 2.7.1 (r271:86832, May 21 2011, 22:52:14)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
py> class C(object):
... def __init__(self):
... self.data = []
... def doit(self, count=0):
... for c in self.data:
... count += c.doit(count)
... count += 1
... print count
... return count
...
py> c = C()
py> c.data.extend([C() for i in xrange(10)])
py> c.doit()
1
2
4
8
16
32
64
128
256
512
1024
1024



WTF?

Put the code into a file, run it -- and be enlightened ;)
 
J

James Stroud

Peter said:
Put the code into a file, run it -- and be enlightened ;)


tal 72% python2.7 eraseme.py
1
2
4
8tal 73% cat eraseme.py
#! /usr/bin/env python

class C:
def __init__(self):
self.data = []
def doit(self, count=0):
for c in self.data:
count += c.doit(count)
count += 1
print count
return count

c = C()
c.data.extend([C() for i in xrange(10)])
c.doit()
tal 74% python2.7 eraseme.py
1
2
4
8
16
32
64
128
256
512
1024


Hmmm. It's still 1024.

What am I missing?

James
 
C

Chris Rebert

The question is "Why is 1024 there at all?" It should be 10.

Ah. This is why it's better to be more explicit about what your
question is than a mere "WTF?".

In that case, I believe you meant to write:
count += c.doit()
rather than:
count += c.doit(count)

Recall that count is continually increasing as you go through your loop.

Although you'll then get 11, not 10, but the cause of that is obvious
(`count += 1`).

Cheers,
Chris
 
J

James Stroud

Peter said:
Put the code into a file, run it -- and be enlightened ;)

Compare the follower to the last.

tal 77% cat eraseme.py
#! /usr/bin/env python

class C:
def __init__(self):
self.data = []
def doit(self, count=[0]):
for c in self.data:
c.doit()
count[0] += 1
print count[0]

c = C()
c.data.extend([C() for i in xrange(10)])
c.doit()
tal 78% python2.7 eraseme.py
1
2
3
4
5
6
7
8
9
10
11

James
 
J

James Stroud

Chris said:
Ah. This is why it's better to be more explicit about what your
question is than a mere "WTF?".

In that case, I believe you meant to write:
count += c.doit()
rather than:
count += c.doit(count)

I get it. Thank you.

James
 
P

Peter Otten

James said:
Peter said:
Put the code into a file, run it -- and be enlightened ;)


tal 72% python2.7 eraseme.py
1
2
4
8tal 73% cat eraseme.py
#! /usr/bin/env python

class C:
def __init__(self):
self.data = []
def doit(self, count=0):
for c in self.data:
count += c.doit(count)
count += 1
print count
return count

c = C()
c.data.extend([C() for i in xrange(10)])
c.doit()
tal 74% python2.7 eraseme.py
1
2
4
8
16
32
64
128
256
512
1024


Hmmm. It's still 1024.

What am I missing?

James

Like Chris I assumed that you wondered why 1024 appeared twice. It turns out
WTF is not a got a good problem description.

Now for a complete run-through, the inner c.doit() has len(c.data) == 0, so
count += c.doit(count) just adds count + 1 and you get 10 iterations:

(1) count=0, print 1, add 1
(2) count=1, print 2, add 2
(3) count=3, print 4, add 4
(4) count=7, print 8, add 8
(5) you get the idea

Another way to look at it: in your special case the inner loop can be
rewritten as

for c in self.data:
print count + 1
count += count + 1
 
R

Roy Smith

James Stroud said:
tal 65% python2.7
Python 2.7.1 (r271:86832, May 21 2011, 22:52:14)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
py> class C(object):
... def __init__(self):
... self.data = []
... def doit(self, count=0):
... for c in self.data:
... count += c.doit(count)
... count += 1
... print count
... return count
...
py> c = C()
py> c.data.extend([C() for i in xrange(10)])
py> c.doit()

I have no idea what this is *supposed* to be doing, so let me toss out
some general debugging ideas;

1) What do you expect [C() for i in xrange(10)] to return? Does it?
Run that part in isolation and see if it does.

2) What do you expect c.data.extend([...]) to return? Does it?

3) What do you expect c.doit() to return for trivial inputs? Does it?
Try calling it with a count of 0, 1, and 2, and see if you get the
result you expect.

In other words, break the problem down into smaller pieces and make sure
each piece works in isolation. When you find some little piece which
isn't doing what you expect, it'll be much easier to debug than trying
to debug the whole thing at once.
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top