list mutability

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • gigs

    list mutability

    hi im having this code

    l = [1, 3, 5, 'D', 1, 2, 3, 4, 5, 6, 7, 'A', 'S', 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 'A']

    why i need to copy x list? can someone explain me. If i dont copy it i get this
    result:
    >>took_num_rang e(l)
    [[1, 2, 3, 4, 5, 6, 7], [6, 5, 4, 3, 2, 1, 0], [6, 5, 4, 3, 2, 1, 0], [6, 5, 4,
    3, 2, 1, 0], [6, 5, 4, 3, 2, 1, 0]]

    but if i copy it i get result as im looking for
    >>took_num_rang e(l)
    [[1, 2, 3, 4, 5, 6, 7], [9, 8, 7, 6, 5, 4, 3], [8, 7, 6, 5, 4, 3, 2], [7, 6, 5,
    4, 3, 2, 1], [6, 5, 4, 3, 2, 1, 0]]
    >>>
    def took_num_range( l):
    j = []
    x = []
    for i in l:
    if type(i) is int and len(x) == 7:
    j.append(x)
    x = x[:] # im mean here
    x.pop(0)
    if type(i) is int and len(x) < 7:
    x.append(i)
    if type(i) is not int and len(x) == 7:
    j.append(x)
    x = []
    if type(i) is not int and len(x) != 7:
    x = []
    return j


    thx
  • John Machin

    #2
    Re: list mutability

    On Feb 19, 5:09 am, gigs <g...@hi.t-com.hrwrote:
    hi im having this code
    >
    l = [1, 3, 5, 'D', 1, 2, 3, 4, 5, 6, 7, 'A', 'S', 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 'A']
    >
    why i need to copy x list? can someone explain me. If i dont copy it i get this
    result:
    >>took_num_rang e(l)
    [[1, 2, 3, 4, 5, 6, 7], [6, 5, 4, 3, 2, 1, 0], [6, 5, 4, 3, 2, 1, 0], [6, 5, 4,
    3, 2, 1, 0], [6, 5, 4, 3, 2, 1, 0]]
    >
    but if i copy it i get result as im looking for
    >>took_num_rang e(l)
    [[1, 2, 3, 4, 5, 6, 7], [9, 8, 7, 6, 5, 4, 3], [8, 7, 6, 5, 4, 3, 2], [7, 6, 5,
    4, 3, 2, 1], [6, 5, 4, 3, 2, 1, 0]]
    >>>
    >
    def took_num_range( l):
    j = []
    x = []
    for i in l:
    if type(i) is int and len(x) == 7:
    j.append(x)
    x = x[:] # im mean here
    x.pop(0)
    j.append(x) saves a reference to the same list that x refers to. So
    when you later mutate that one list, all references in j refer to the
    mutated list.

    Instead of
    x = x[:]
    x.pop(0)
    which copies the contents twice, you can do
    x = x[1:]

    In a more complicated example, it would be better to take a copy at
    each point:

    j.append(x[:])

    .... then you are sure you have a photo of x and it doesn't matter how/
    when you mutate x later.
    if type(i) is int and len(x) < 7:
    This is a big trap for the casual reader (len(x) may have changed
    since the previous "if" statement) ... see below.
    x.append(i)
    if type(i) is not int and len(x) == 7:
    j.append(x)
    x = []
    if type(i) is not int and len(x) != 7:
    x = []
    What do you want to do if your input ends with 7 integers and no
    letter, e.g.
    [1,2,3,'A',1,2,3 ,4,5,6,7]
    ?
    return j
    Some suggestions:
    1. use meaningful names
    2. don't have hard-wired numbers like 7
    3. use "else" and "elif" as appropriate to avoid repeating conditions
    unnecessarily.

    Here's a suggested replacement for your code, tested to the extent
    shown:

    C:\junk>type tooknumrange.py
    def took_num_range( seq, size, grab_end=False) :
    result = []
    queue = []
    for item in seq:
    if isinstance(item , int):
    if len(queue) == size:
    result.append(q ueue)
    queue = queue[1:]
    queue.append(it em)
    else:
    if len(queue) == size:
    result.append(q ueue)
    queue = []
    if grab_end and len(queue) == size:
    result.append(q ueue)
    return result

    test1 = [
    1, 3, 5, 'D',
    1, 2, 3, 4, 5, 6, 7, 'A',
    'S',
    9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 'A',
    ]
    test1r = [
    [1, 2, 3, 4, 5, 6, 7],
    [9, 8, 7, 6, 5, 4, 3],
    [8, 7, 6, 5, 4, 3, 2],
    [7, 6, 5, 4, 3, 2, 1],
    [6, 5, 4, 3, 2, 1, 0],
    ]
    test2 = [1, 2, 3, 4, 5]
    test2r = [[1, 2, 3, 4, 5]] ### or is it [] ???
    tests = [
    (test1, test1r, 7, False),
    (test2, [], 5, False),
    (test2, test2r, 5, True),
    ]

    failed = 0
    for tno, (tseq, tresult, tsize, tgrab) in enumerate(tests ):
    aresult = took_num_range( tseq, tsize, grab_end=tgrab)
    if aresult != tresult:
    failed += 1
    print 'Test %d failed' % (tno+1)
    print 'Expected:', tresult
    print 'Actual :', aresult
    print 'Failed %d test(s) out of %d' % (failed, len(tests))


    C:\junk>tooknum range.py
    Failed 0 test(s) out of 3

    HTH,
    John

    Comment

    Working...