1

I am trying to append many variables that are zeep objects to a list. However, when I print out the list at the end, each variable in the list has the same data.

I have tried isolating when the variable gets overwritten, and it's happening when I put a new value into the variable with the same name, but I do this after I append the variable to the list. So I am confused as to why this is happening. I've tried to use different variable names, but it results in the same problem.

def create_json_list(json_template):
    newVar = json_template
    newVar['name'] = unique_name
    list.append(newVar)

    newVar = json_template
    newVar['name'] = unique_name2
    list.append(newVar)


    print(list[0]['name'])
    print(list[1]['name'])
# At this point, the same name gets printed twice
Puffs550
  • 11
  • 2
  • What is the type and value of `json_template`? Please use the [edit] link below your post to update it with additional info. – Gino Mempin Jun 20 '19 at 23:32
  • I just learned that it's a zeep object, not just plain json, i don't know if that makes a big difference, i dont even know what a zeep object is. – Puffs550 Jun 20 '19 at 23:36
  • 1
    Possible duplicate of [How to copy a dictionary and only edit the copy](https://stackoverflow.com/questions/2465921/how-to-copy-a-dictionary-and-only-edit-the-copy) –  Jun 21 '19 at 00:00

1 Answers1

0

You are appending the same object to the list multiple times. If you notice, the template is getting modified:

import json

template = {
    "field1": 1,
    "field2": "two"
}

json_list = list()

def create_json_list(json_template):
    newVar = json_template
    newVar['name'] = "unique_name"
    json_list.append(newVar)

    newVar = json_template
    newVar['name'] = 'another_unique_name'
    json_list.append(newVar)

    print(json.dumps(json_template, indent=4))

create_json_list(template)

Output

{
    "field2": "two", 
    "field1": 1, 
    "name": "another_unique_name"
}

You need to create a new template for each entry:

newVar = dict(json_template)

From the documenation:

Assignment statements in Python do not copy objects, they create
bindings between a target and an object.

If you want to copy an object, you need to let Python know. In the case of a dict, you can just use the constructor as shown above.

For a zeep object, you should be able to use a factory:

factory = client.type_factory('ns0')
newVar = factory.JsonTemplate({"field1": 1, "field2": "two"})
  • Thank you for your help. Why/how is it that the json_template is getting modified if I'm never assigning anything to it? – Puffs550 Jun 20 '19 at 23:58
  • You can think of `newVar = json_template` as telling Python that you want to use a new name to refer to `json_template`. Any modification of `newVar` is a modification of `json_template`. You need to make a new copy of `json_template` every time you need one. –  Jun 21 '19 at 00:09
  • Okay amazing it works. A follow up, do you know if there is way to make a copy of a zeep object by chance? Right now i have to convert from zeep to dict to then be able to make copies, but I'd prefer if i could make a copy from the zeep itself. – Puffs550 Jun 21 '19 at 00:30
  • Have a look at [Using factories](https://python-zeep.readthedocs.io/en/master/datastructures.html#using-factories) in the [zeep documentation](https://python-zeep.readthedocs.io/en/master/index.html). –  Jun 21 '19 at 00:33