Critique of first python code

Discussion in 'Python' started by Zack, Feb 8, 2008.

  1. Zack

    Zack Guest

    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
    Zack, Feb 8, 2008
    #1
    1. Advertising

  2. On Feb 8, 7:20 pm, "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 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
    Arnaud Delobelle, Feb 8, 2008
    #2
    1. Advertising

  3. 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
    Tomek Paczkowski, Feb 8, 2008
    #3
  4. On Feb 8, 3:40 pm, Arnaud Delobelle <> wrote:

    > On Feb 8, 7:20 pm, "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 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
    George Sakkis, Feb 8, 2008
    #4
  5. Zack

    Zack Guest

    On Feb 8, 4:32 pm, George Sakkis <> wrote:
    > On Feb 8, 3:40 pm, Arnaud Delobelle <> 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
    Zack, Feb 9, 2008
    #5
  6. Zack

    TerryP Guest

    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
    TerryP, Feb 17, 2008
    #6
  7. Zack

    John Machin Guest

    On Feb 17, 4:42 pm, TerryP <> 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.
    John Machin, Feb 17, 2008
    #7
  8. Zack

    Dan Bishop Guest

    On Feb 8, 7:30 pm, Zack <> 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).
    Dan Bishop, Feb 17, 2008
    #8
  9. 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
    Matthew Marshall, Feb 17, 2008
    #9
  10. On Feb 17, 10:17 am, Matthew Marshall <>
    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
    George Sakkis, Feb 17, 2008
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ryan Stewart

    Code critique (no URL available)

    Ryan Stewart, Apr 26, 2004, in forum: HTML
    Replies:
    3
    Views:
    461
    Ryan Stewart
    Apr 26, 2004
  2. cs

    Request critique of first program

    cs, Sep 2, 2007, in forum: C Programming
    Replies:
    3
    Views:
    270
  3. cs

    Request critique of first program

    cs, Sep 2, 2007, in forum: C Programming
    Replies:
    14
    Views:
    479
    Keith Thompson
    Sep 4, 2007
  4. voipfc
    Replies:
    0
    Views:
    125
    voipfc
    Oct 11, 2006
  5. kazack
    Replies:
    3
    Views:
    255
    Tad McClellan
    Oct 22, 2003
Loading...

Share This Page