DonCallisto
DonCallisto

Reputation: 29932

List and append elements

Something strange - at least to me - is happening in this snippet of code.

I have a function that I recall from a WS method. My function is something like this:

try:       
    tipo = d['id_tipo_offerta']
    params = OFFERTA_MAP_DICT[tipo]
    params.append('days_constraints')
except Exception, s:
    self.log_int_raise("core.struttura._parseDictOfferta(): 1 Error=%s", RED(s))

Omitting the content of OFFERTA_MAP_DICT (in this specific case is an empty list) I want to know why, if I call this function the first time, value of params will be ['days_constraints'] and every other time I recall still this function, value of params will be ['days_constraints','days_constraints',....,'days_constraints'] with n elements where n is the number of time that I recall this function.

Is my first assignment done by reference?

Edit:

Those are my maps

OFFERTA_MAP_DICT= {
        ID_OFFERTA_SCONTOCAMERA:    ID_OFFERTA_SCONTOCAMERA_KEYS,
        ID_OFFERTA_BEFOREDATE:      ID_OFFERTA_BEFOREDATE_KEYS,
        ID_OFFERTA_BEFORENDAYS:     ID_OFFERTA_BEFORENDAYS_KEYS,
        ID_OFFERTA_XFORY:           ID_OFFERTA_XFORY_KEYS,
        ID_OFFERTA_SCALARE:         ID_OFFERTA_SCALARE_KEYS,
        ID_OFFERTA_PACCHETTI:       ID_OFFERTA_PACCHETTI_KEYS,
        ID_OFFERTA_LAST_MINUTE:     ID_OFFERTA_LAST_MINUTE_KEYS,
        ID_OFFERTA_ADVANCE:         ID_OFFERTA_ADVANCE_KEYS
        }


OFFERTA_ROOM_MAP_DICT= {
        ID_OFFERTA_SCONTOCAMERA:    ['id_tipo_sconto', 'valore_sconto', 'id_tipo_prezzo'],
        ID_OFFERTA_BEFOREDATE:      ['id_tipo_sconto', 'valore_sconto', 'id_tipo_prezzo'],
        ID_OFFERTA_BEFORENDAYS:     ['id_tipo_sconto', 'valore_sconto', 'id_tipo_prezzo'],
        ID_OFFERTA_XFORY:           [],
        ID_OFFERTA_SCALARE:         [],
        ID_OFFERTA_PACCHETTI:       ['prezzo'],
        ID_OFFERTA_LAST_MINUTE:     ['id_tipo_sconto', 'valore_sconto', 'id_tipo_prezzo']
        }

Upvotes: 2

Views: 290

Answers (4)

kindall
kindall

Reputation: 184385

params is a reference to the same list each time you call the function, and this is the same list as OFFERTA_MAP_DICT[tipo]. So you are repeatedly appending that text to the same list each time.

All assignments in Python assign references. Copying a list can be done in a few ways:

params = OFFERTA_MAP_DICT[tipo][:]       # take slice of whole list
params = list(OFFERTA_MAP_DICT[tipo])    # construct new list
params = copy(OFFERTA_MAP_DICT[tipo])    # from copy import copy

Upvotes: 0

mgilson
mgilson

Reputation: 310227

It is pretty difficult to really grasp what is happening in your code. However, when you do:

params = OFFERTA_MAP_DICT[tipo]

params is a reference to the same list stored in the OFFERTA_MAP_DICT. When you append to that list, you'll also see that change reflected in OFFERTA_MAP_DICT because they share a reference.

Upvotes: 0

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 799370

Assignment is always done by reference. If you want to make a (shallow) copy of a list then slice it.

lnew = lold[:]

Upvotes: 2

Stu Cox
Stu Cox

Reputation: 4527

The statement params = OFFERTA_MAP_DICT[tipo] assigns OFFERTA_MAP_DICT[tipo] to the variable name params... it doesn't copy it. As OFFERTA_MAP_DICT[tipo] is a list, params now just points to the same list.

So when you do params.append('days_constraints'), you're appending to the list OFFERTA_MAP_DICT[tipo]... so when you next come into this block of code, OFFERTA_MAP_DICT[tipo] already has 'days_constraints' appended, which you then append again, etc.

You can perform a copy (or deep copy) with the copy module, but depending on how you're using params later on, I suspect there may be a better way to go about it.

Upvotes: 1

Related Questions