Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Critique of first python code

Reply
Thread Tools

Critique of first python code

 
 
Zack
Guest
Posts: n/a
 
      02-08-2008
Hi all. I'm just starting to pick up python. I wanted to play with nested
lists so first I wrote a little bit of code to create arbitrarily nested
lists (grow). Then I wrote a breadth first search. I'm putting this small
snippet up asking for criticism. Was there a more elegant way to do what I'm
doing? Anything that goes against convention? Anything that fingers me as a
c++ programmer? Are there standard modules that do these kind of things?
Thanks for any feedback.

##############################
from random import randint

Val = 0

def grow(L,depth):
'''grows L by appending integers and arbitrarily nested lists with a
maximum
depth. Returns L.'''
global Val
if depth == 0:
return L
else:
choice = randint(1,2)
if 1 == choice:
# add a numerical literal
Val += 1
L.append(Val)
return grow(L,depth-1)
elif 2 == choice:
# add a list
L.append( grow([],depth-1) )
return grow(L,depth-1)

def traverse(L, count=0):
'''Prints the non iterable object of L in breadth first order.
Returns count + the number of non iterables in L.'''
if L == []:
return count
n = []
for e in L:
if not hasattr(e,'__iter__'):
print e,
count += 1
else:
n[:] += e
print '\n'
return traverse(n,count)

L = grow([],10)
C = traverse(L)
##############################


--
Zack

 
Reply With Quote
 
 
 
 
Arnaud Delobelle
Guest
Posts: n/a
 
      02-08-2008
On Feb 8, 7:20*pm, "Zack" <(E-Mail Removed)> wrote:
> Hi all. I'm just starting to pick up python. I wanted to play with nested
> lists so first I wrote a little bit of code to create arbitrarily nested
> lists (grow). Then I wrote a breadth first search. *I'm putting this small
> snippet up asking for criticism. Was there a more elegant way to do what I'm
> doing? Anything that goes against convention? *Anything that fingers me as a
> c++ programmer? Are there standard modules that do these kind of things?
> Thanks for any feedback.
>
> ##############################
> from random import randint
>
> Val = 0
>
> def grow(L,depth):
> * *'''grows L by appending integers and arbitrarily nested lists with a
> maximum
> * *depth. Returns L.'''
> * *global Val
> * *if depth == 0:
> * * * return L
> * *else:
> * * * choice = randint(1,2)
> * * * if 1 == choice:
> * * * * *# add a numerical literal
> * * * * *Val += 1
> * * * * *L.append(Val)
> * * * * *return grow(L,depth-1)
> * * * elif 2 == choice:
> * * * * *# add a list
> * * * * *L.append( grow([],depth-1) )
> * * * * *return grow(L,depth-1)


How about:

from itertools import count
from random import randrange

def grow(L, depth, counter=count()):
'''grow L by appending integers and arbitrarily nested lists with a
maximum depth. Returns L.'''
if depth == 0:
return L
else:
L.append(counter.next() if randrange(2) else grow([], depth-1))
return grow(L, depth-1)


> def traverse(L, count=0):
> * *'''Prints the non iterable object of L in breadth first order.
> * *Returns count + the number of non iterables in L.'''
> * *if L == []:
> * * * return count
> * *n = []
> * *for e in L:
> * * * if not hasattr(e,'__iter__'):
> * * * * *print e,
> * * * * *count += 1
> * * * else:
> * * * * *n[:] += e

I would write n.extend(e) here (or n += e)
> * *print '\n'
> * *return traverse(n,count)
>
> L = grow([],10)
> C = traverse(L)
> ##############################
>
> --
> Zack


--
Arnaud

 
Reply With Quote
 
 
 
 
Tomek Paczkowski
Guest
Posts: n/a
 
      02-08-2008
Zack wrote:

> Hi all. I'm just starting to pick up python. I wanted to play with nested
> lists so first I wrote a little bit of code to create arbitrarily nested
> lists (grow). Then I wrote a breadth first search. I'm putting this small
> snippet up asking for criticism. Was there a more elegant way to do what
> ...


You can try to put your code through pylint. It will give you some automatic
critique.

--
Oinopion

 
Reply With Quote
 
George Sakkis
Guest
Posts: n/a
 
      02-08-2008
On Feb 8, 3:40 pm, Arnaud Delobelle <(E-Mail Removed)> wrote:

> On Feb 8, 7:20 pm, "Zack" <(E-Mail Removed)> wrote:
>
>
>
> > Hi all. I'm just starting to pick up python. I wanted to play with nested
> > lists so first I wrote a little bit of code to create arbitrarily nested
> > lists (grow). Then I wrote a breadth first search. I'm putting this small
> > snippet up asking for criticism. Was there a more elegant way to do what I'm
> > doing? Anything that goes against convention? Anything that fingers me as a
> > c++ programmer? Are there standard modules that do these kind of things?
> > Thanks for any feedback.

>
> > ##############################
> > from random import randint

>
> > Val = 0

>
> > def grow(L,depth):
> > '''grows L by appending integers and arbitrarily nested lists with a
> > maximum
> > depth. Returns L.'''
> > global Val
> > if depth == 0:
> > return L
> > else:
> > choice = randint(1,2)
> > if 1 == choice:
> > # add a numerical literal
> > Val += 1
> > L.append(Val)
> > return grow(L,depth-1)
> > elif 2 == choice:
> > # add a list
> > L.append( grow([],depth-1) )
> > return grow(L,depth-1)

>
> How about:
>
> from itertools import count
> from random import randrange
>
> def grow(L, depth, counter=count()):
> '''grow L by appending integers and arbitrarily nested lists with a
> maximum depth. Returns L.'''
> if depth == 0:
> return L
> else:
> L.append(counter.next() if randrange(2) else grow([], depth-1))
> return grow(L, depth-1)


Or you may write a more flexible generator version of the above. If
you're not familiar with generators, think of them as lazy sequences
that generate successive elements only when needed:

import random
from itertools import count

def igrow(depth, next=count(1).next, nest=list, random=random.random):
'''Generate integers and arbitrarily nested iterables with a
maximum depth.'''
if depth:
depth -= 1
yield next() if random()<0.5 else
nest(igrow(depth,next,nest,random))
for e in igrow(depth,next,nest,random):
yield e


With this you can just as easily generate nested tuples (or other
containers) instead of lists:

nested = tuple(igrow(10, nest=tuple))

You may even avoid allocating nested containers altogether:

from types import GeneratorType

for x in igrow(10, nest=iter):
if isinstance(x, GeneratorType):
# process nested generator
else:
# x is an 'atom'


HTH,
George
 
Reply With Quote
 
Zack
Guest
Posts: n/a
 
      02-09-2008
On Feb 8, 4:32 pm, George Sakkis <(E-Mail Removed)> wrote:
> On Feb 8, 3:40 pm, Arnaud Delobelle <(E-Mail Removed)> wrote:
>
>
>

<snip my original post>
> > How about:

>
> > from itertools import count
> > from random import randrange

>
> > def grow(L, depth, counter=count()):
> > '''grow L by appending integers and arbitrarily nested lists with a
> > maximum depth. Returns L.'''
> > if depth == 0:
> > return L
> > else:
> > L.append(counter.next() if randrange(2) else grow([], depth-1))
> > return grow(L, depth-1)

>
> Or you may write a more flexible generator version of the above. If
> you're not familiar with generators, think of them as lazy sequences
> that generate successive elements only when needed:
>
> import random
> from itertools import count
>
> def igrow(depth, next=count(1).next, nest=list, random=random.random):
> '''Generate integers and arbitrarily nested iterables with a
> maximum depth.'''
> if depth:
> depth -= 1
> yield next() if random()<0.5 else
> nest(igrow(depth,next,nest,random))
> for e in igrow(depth,next,nest,random):
> yield e
>
> With this you can just as easily generate nested tuples (or other
> containers) instead of lists:
>
> nested = tuple(igrow(10, nest=tuple))
>
> You may even avoid allocating nested containers altogether:
>
> from types import GeneratorType
>
> for x in igrow(10, nest=iter):
> if isinstance(x, GeneratorType):
> # process nested generator
> else:
> # x is an 'atom'
>
> HTH,
> George


The generators you show here are interesting, and it prodded me on how
to add tuples but at the moment (I'm a python newbie) the generator
seems less readable to me than the alternative. After some input from
Scott David Daniels I changed some of the unnecessary recursion to
while loops. I completely over thought my problem. I've fetched pylint
and I'll be sure to keep it in my toolkit. What does everyone think of
the code below? Are generator functions a more pythonic (preferred?)
way of doing things or will my while loops escape mocking? Thanks for
the feedback this has been a great exercise for me.

import random
from itertools import count

_Val = count(1)

def grow(seq, depth):
'''
Grows seq with arbitrarily appended integers, lists and tuples.

At least depth elements will be added to seq and seq will not grow
more than depth levels deep.
Returns seq.

'''
while depth > 0:
choice = random.random()
if choice < .5:
seq.append(_Val.next())
elif choice < .75:
seq.append(list(grow([], depth-1)))
else:
seq.append(tuple(grow([], depth-1)))
depth -= 1
return seq


def traverse(seq):
'''
Breadth first traversal of seq.

Prints the non iterable objects of seq in breadth first order.
Returns the number of atoms (non iterables) in seq.

'''
counter = 0
while seq:
below = []
for item in seq:
if hasattr(item, '__iter__'):
below.extend(item)
else:
print item,
counter += 1
#intentional blank line to distinguish long lines that wrap
print '\n'
seq = below
return counter

L = grow([],10)
C = traverse(L)


--
Zack

 
Reply With Quote
 
TerryP
Guest
Posts: n/a
 
      02-17-2008
Tomek Paczkowski wrote:
> You can try to put your code through pylint. It will give you some
> automatic critique.
>


There is a pylint !?

That one is defiantly making my workstation later just for fun hehe.

--
There seems no plan because it is all plan.
-- C.S. Lewis
 
Reply With Quote
 
John Machin
Guest
Posts: n/a
 
      02-17-2008
On Feb 17, 4:42 pm, TerryP <(E-Mail Removed)> wrote:
> Tomek Paczkowski wrote:
> > You can try to put your code through pylint. It will give you some
> > automatic critique.

>
> There is a pylint !?
>
> That one is defiantly making my workstation later just for fun hehe.
>


See if you can find an englint while you are at it hehehe.

 
Reply With Quote
 
Dan Bishop
Guest
Posts: n/a
 
      02-17-2008
On Feb 8, 7:30 pm, Zack <(E-Mail Removed)> wrote:
>[snip]
>
> The generators you show here are interesting, and it prodded me on how
> to add tuples but at the moment (I'm a python newbie) the generator
> seems less readable to me than the alternative. After some input from
> Scott David Daniels I changed some of the unnecessary recursion to
> while loops. I completely over thought my problem. I've fetched pylint
> and I'll be sure to keep it in my toolkit. What does everyone think of
> the code below? Are generator functions a more pythonic (preferred?)
> way of doing things or will my while loops escape mocking? Thanks for
> the feedback this has been a great exercise for me.
>
>[code example snipped]


Your functions look like good candidates for generators, but I
wouldn't mock you for using while loops.

I will say, however, that hasattr(item, '__iter__') isn't a perfect
way of checking whether an object is iterable: Objects that just
define __getitem__ are iterable too (e.g., UserList).
 
Reply With Quote
 
Matthew Marshall
Guest
Posts: n/a
 
      02-17-2008
Dan Bishop wrote:
> I will say, however, that hasattr(item, '__iter__') isn't a perfect
> way of checking whether an object is iterable: Objects that just
> define __getitem__ are iterable too (e.g., UserList).


Speaking of which, what *is* the best way to check if an object is
iterable?

I always wrap iter(item) in a try/except block, but is there an
isiterable() function somewhere?

MWM
 
Reply With Quote
 
George Sakkis
Guest
Posts: n/a
 
      02-17-2008
On Feb 17, 10:17 am, Matthew Marshall <(E-Mail Removed)>
wrote:
> Dan Bishop wrote:
> > I will say, however, that hasattr(item, '__iter__') isn't a perfect
> > way of checking whether an object is iterable: Objects that just
> > define __getitem__ are iterable too (e.g., UserList).

>
> Speaking of which, what *is* the best way to check if an object is
> iterable?
>
> I always wrap iter(item) in a try/except block,


Yes, that's the most foolproof way.

> but is there an
> isiterable() function somewhere?


Not AFAIK, but if I had to write one, I would use

isiterable = lambda x: hasattr(x, '__iter__') or
hasattr(x, '__getitem__')


In Python 3 it will be isinstance(x, Iterable).

George
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Learning Python: Code critique please macoovacany Python 2 06-23-2008 12:01 AM
Request critique of first program cs C Programming 14 09-04-2007 01:01 AM
Request critique of first program cs C Programming 3 09-03-2007 05:17 AM
My First Almost Serious Ruby Program - Critique it voipfc Ruby 0 10-11-2006 02:58 PM
First Perl/CGI need critique on current code before further developement kazack Perl Misc 3 10-22-2003 03:32 AM



Advertisments