Asked  7 Months ago    Answers:  5   Viewed   36 times

Please consider the following code:

i = [1, 2, 3, 5, 8, 13]
j = []
k = 0

for l in i:
    j[k] = l
    k += 1

print j

The output (Python 2.6.6 on Win 7 32-bit) is:

> Traceback (most recent call last): 
>     j[k] = l IndexError: list assignment index out of range

I guess it's something simple I don't understand. Can someone clear it up?

 Answers

13

j is an empty list, but you're attempting to write to element [0] in the first iteration, which doesn't exist yet.

Try the following instead, to add a new element to the end of the list:

for l in i:
    j.append(l)

Of course, you'd never do this in practice if all you wanted to do was to copy an existing list. You'd just do:

j = list(i)

Alternatively, if you wanted to use the Python list like an array in other languages, then you could pre-create a list with its elements set to a null value (None in the example below), and later, overwrite the values in specific positions:

i = [1, 2, 3, 5, 8, 13]
j = [None] * len(i)
#j == [None, None, None, None, None, None]
k = 0

for l in i:
   j[k] = l
   k += 1

The thing to realise is that a list object will not allow you to assign a value to an index that doesn't exist.

Tuesday, June 1, 2021
 
RahulG
answered 7 Months ago
59

Just use a containment test:

if redList in totalList:

This returns True for your sample data:

>>> totalList = [ [[0,1], [2,7], [6,3]], [[2,3], [6,1], [4,1]] ]
>>> redList = [ [0,1], [2,7], [6,3] ]
>>> redList in totalList
True
Thursday, August 5, 2021
 
TMichel
answered 5 Months ago
49

It seems like your problem is pretty straightforward. You probably have a list named row and you're trying to assign values to non-existent indices

>>> row = []
>>> row[0] = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range

If however you appended a new list into the row list like I think you want to do

>>> row = []
>>> row.append([1, 2, 3, 4])
>>> row
[[1, 2, 3, 4]]
>>> row[0][0]
1

This would work fine. If you're trying to triple nest things

>>> row = []
>>> row.append([[1,2,3,4]])
>>> row
[[[1, 2, 3, 4]]]
>>> row[0].append([-1, -2, -3, -4])
>>> row
[[[1, 2, 3, 4], [-1, -2, -3, -4]]]

You can use the same syntax

Friday, August 20, 2021
 
chugadie
answered 4 Months ago
67

In addition to Francesco's answer, it seems that one of the (relatively) expensive part of the catch is the exception matching:

>>> timeit.timeit('try:n    raise KeyErrornexcept KeyError:n    pass', number=1000000 )
1.1587663322268327
>>> timeit.timeit('try:n    raise KeyErrornexcept:n    pass', number=1000000 )
0.9180641582179874

Looking at the (CPython 2) disassembly:

>>> def f():
...     try:
...         raise KeyError
...     except KeyError:
...         pass
... 
>>> def g():
...     try:
...         raise KeyError
...     except:
...         pass
... 
>>> dis.dis(f)
  2           0 SETUP_EXCEPT            10 (to 13)

  3           3 LOAD_GLOBAL              0 (KeyError)
              6 RAISE_VARARGS            1
              9 POP_BLOCK           
             10 JUMP_FORWARD            17 (to 30)

  4     >>   13 DUP_TOP             
             14 LOAD_GLOBAL              0 (KeyError)
             17 COMPARE_OP              10 (exception match)
             20 POP_JUMP_IF_FALSE       29
             23 POP_TOP             
             24 POP_TOP             
             25 POP_TOP             

  5          26 JUMP_FORWARD             1 (to 30)
        >>   29 END_FINALLY         
        >>   30 LOAD_CONST               0 (None)
             33 RETURN_VALUE        
>>> dis.dis(g)
  2           0 SETUP_EXCEPT            10 (to 13)

  3           3 LOAD_GLOBAL              0 (KeyError)
              6 RAISE_VARARGS            1
              9 POP_BLOCK           
             10 JUMP_FORWARD             7 (to 20)

  4     >>   13 POP_TOP             
             14 POP_TOP             
             15 POP_TOP             

  5          16 JUMP_FORWARD             1 (to 20)
             19 END_FINALLY         
        >>   20 LOAD_CONST               0 (None)
             23 RETURN_VALUE        

Note that the catch block loads the Exception anyway and matches it against a KeyError. Indeed, looking at the except KeyError as ke case:

>>> def f2():
...     try:
...         raise KeyError
...     except KeyError as ke:
...         pass
... 
>>> dis.dis(f2)
  2           0 SETUP_EXCEPT            10 (to 13)

  3           3 LOAD_GLOBAL              0 (KeyError)
              6 RAISE_VARARGS            1
              9 POP_BLOCK           
             10 JUMP_FORWARD            19 (to 32)

  4     >>   13 DUP_TOP             
             14 LOAD_GLOBAL              0 (KeyError)
             17 COMPARE_OP              10 (exception match)
             20 POP_JUMP_IF_FALSE       31
             23 POP_TOP             
             24 STORE_FAST               0 (ke)
             27 POP_TOP             

  5          28 JUMP_FORWARD             1 (to 32)
        >>   31 END_FINALLY         
        >>   32 LOAD_CONST               0 (None)
             35 RETURN_VALUE    

The only difference is a single STORE_FAST to store the exception value (in case of a match). Similarly, having several exception matches:

>>> def f():
...     try:
...         raise ValueError
...     except KeyError:
...         pass
...     except IOError:
...         pass
...     except SomeOtherError:
...         pass
...     except:
...         pass
... 
>>> dis.dis(f)
  2           0 SETUP_EXCEPT            10 (to 13)

  3           3 LOAD_GLOBAL              0 (ValueError)
              6 RAISE_VARARGS            1
              9 POP_BLOCK           
             10 JUMP_FORWARD            55 (to 68)

  4     >>   13 DUP_TOP             
             14 LOAD_GLOBAL              1 (KeyError)
             17 COMPARE_OP              10 (exception match)
             20 POP_JUMP_IF_FALSE       29
             23 POP_TOP             
             24 POP_TOP             
             25 POP_TOP             

  5          26 JUMP_FORWARD            39 (to 68)

  6     >>   29 DUP_TOP             
             30 LOAD_GLOBAL              2 (IOError)
             33 COMPARE_OP              10 (exception match)
             36 POP_JUMP_IF_FALSE       45
             39 POP_TOP             
             40 POP_TOP             
             41 POP_TOP             

  7          42 JUMP_FORWARD            23 (to 68)

  8     >>   45 DUP_TOP             
             46 LOAD_GLOBAL              3 (SomeOtherError)
             49 COMPARE_OP              10 (exception match)
             52 POP_JUMP_IF_FALSE       61
             55 POP_TOP             
             56 POP_TOP             
             57 POP_TOP             

  9          58 JUMP_FORWARD             7 (to 68)

 10     >>   61 POP_TOP             
             62 POP_TOP             
             63 POP_TOP             

 11          64 JUMP_FORWARD             1 (to 68)
             67 END_FINALLY         
        >>   68 LOAD_CONST               0 (None)
             71 RETURN_VALUE      

Will duplicate the exception and try to match it against every exception listed, one by one until it founds a match, which is (probably) what is being hinted at as 'poor catch performance'.

Friday, October 29, 2021
 
Vector
answered 1 Month ago
48

You need to return a dictionary of dictionary for functional fields. You defined res as list and tried to assign as the dictionary. res[perfo.id] is considered as list and index value perfo.id is not found in the res list. That is what the error says. Now the code will be

class calculator(osv.osv):
    _name = 'calculator.calculator'

    def get_total(self, cr, uid, ids, field_name, arg, context):
        res = {}
        for perfos in self.browse(cr, uid, ids, context):
            res[perfos.id] = perfos.p + perfos.b
        return res

    _columns = {
        'p':fields.selection(((1,'Outstanding'), (2,'Well Above Expectations'), (3,'As Expected'), (4,'Below Expectations'), (5,'VeryPoor'), (0,'N/A')),'title'),
        'b':fields.selection(((1,'Outstanding'), (2,'Well Above Expectations'), (3,'As Expected'), (4,'Below Expectations'), (5,'Very Poor'), (0,'N/A')),'title'),
        'total' : fields.function(get_total, method=True, string='Total Mark'),
    }

For the above code you probably get this js error Error: [_.sprintf] expecting number but found string

I don't get the point adding up two selection fields. The key will get added up like 1+1 in a unicode format.

This following code will give you the basic idea of functional fields.

class calculator(osv.osv):
    _name = 'calculator.calculator'

    def get_total(self, cr, uid, ids, field_name, arg, context):
        res = {}
        for perfos in self.browse(cr, uid, ids, context):
            res[perfos.id] = perfos.p + perfos.b
        return res

    _columns = {
        'p':fields.integer('A'),
        'b':fields.integer('B'),
        'total' : fields.function(get_total, method=True, string='Total Mark'),
        }

You may need to look at How to set store trigger for computed fields in Odoo 8?

Function field is not working in OpenERP

Saturday, December 4, 2021
 
Andreas
answered 5 Days ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share