0

i have 3 classes for a project that look like this:

class Customer():

    def __init__(self, name, name_short=None, parent_page_id=None, base_url=None, space=None, clusters=[]):
            self.name = name
            self.name_short = name_short
            self.parent_page_id = parent_page_id
            self.base_url = _base_url
            self.space = space
            self.clusters = clusters

    def add_cluster_to_customer(self, cluster):
        self.clusters.append(cluster)
    
    def write_customer_to_db(self):
        pass

    @classmethod
    def load_customer_from_file(cls, name):
        clusters = {}
        customer_config = yaml.safe_load(open(f'{CUSTOMER_DIR}/{name}{CONFIG.customer_file_extension}'))
        for cluster_name, cluster_config in customer_config['clusters'].items():
            cluster_obj = Cluster(cluster_name)
            for device in cluster_config['devices']:
                dev_obj = Device(device['name'], device['ip_address'])
                cluster_obj.add_device_to_cluster(dev_obj)
            clusters[cluster_name] = cluster_obj

        return cls( name=customer_config['name'], 
                    name_short=customer_config['name_short'],
                    parent_page_id=customer_config['parent_page_id'],
                    base_url=customer_config['base_url'],
                    space=customer_config['space'],
                    clusters=clusters)

class Cluster():
    def __init__(self, cluster_name, devices=[]):
        self.cluster_name = cluster_name
        self.devices = devices

    def add_device_to_cluster(self, device):
        self.devices.append(device)

class Device():
    def __init__(self, device_name, device_ip):
        self.device_name = device_name
        self.device_ip = device_ip

The data that gets fed into the class method looks like this:

clusters:
  labor:
    cluster_name_short: LAB
    service: Labor
    cluster_description: Test cluster description
    service_description: Test service description
    devices:
      - name: x
        ip_address: xxxx
      - name: y
        ip_address: yyyy
  production:
    cluster_name_short: PROD
    service: Production
    cluster_description: Production cluster description
    service_description: Production service description
    devices:
      - name: a
        ip_address: aaaa
      - name: b
        ip_address: bbbb

If i create an instance with 'customer = Customer.load_customer_from_file(name=customer_name)' i would expect to get a customer instance that has 2 clusters, with 2 devices each. Like so:

clusters:{'labor': <automatic_documenta...c26342fe0>}
   'labor':<automatic_documentation.assets.Cluster object at 0x7f1c26342fe0>
   cluster_name:'labor'
   devices:[<automatic_documenta...c26341de0>, <automatic_documenta...c26343460>]
   0:<automatic_documentation.assets.Device object at 0x7f1c26341de0>
      device_ip:'xxxx'
      device_name:'x'
   1:<automatic_documentation.assets.Device object at 0x7f1c26343460>
      device_ip:'yyyy'
      device_name:'y'
   'production':<automatic_documentation.assets.Cluster object at 0x7f2c55029e10>
   cluster_name:'production'
   devices:[<automatic_documenta...c5d1a2bf0>, <automatic_documenta...c5502abc0>]
   0:<automatic_documentation.assets.Device object at 0x7f2c5d1a2bf0>
      device_ip:'aaaa'
      device_name:'a'
   1:<automatic_documentation.assets.Device object at 0x7f2c5502abc0>
      device_ip:'bbbb'
      device_name:'b'

but instead, i get 2 clusters with 4 devices in it, like so:

'labor':<automatic_documentation.assets.Cluster object at 0x7fb8a5441de0>
cluster_name:'labor'
devices:[<automatic_documenta...8ad666440>, <automatic_documenta...8a54428f0>, <automatic_documenta...8a57ef010>, <automatic_documenta...8a5442a70>]
    0:<automatic_documentation.assets.Device object at 0x7fb8ad666440>
    1:<automatic_documentation.assets.Device object at 0x7fb8a54428f0>
    2:<automatic_documentation.assets.Device object at 0x7fb8a57ef010>
    3:<automatic_documentation.assets.Device object at 0x7fb8a5442a70>
'production':<automatic_documentation.assets.Cluster object at 0x7fb8a5443070>
cluster_name:'production'
devices:[<automatic_documenta...8ad666440>, <automatic_documenta...8a54428f0>, <automatic_documenta...8a57ef010>, <automatic_documenta...8a5442a70>]
    0:<automatic_documentation.assets.Device object at 0x7fb8ad666440>
    1:<automatic_documentation.assets.Device object at 0x7fb8a54428f0>
    2:<automatic_documentation.assets.Device object at 0x7fb8a57ef010>
    3:<automatic_documentation.assets.Device object at 0x7fb8a5442a70>

Now i know that stuff like this can happen, because how references in python works and i thought that this line:

cluster_obj = Cluster(cluster_name)

could be the problem. But as far as i know, when you create a new instance of a class, it should not interfere with the old one. I checked, and i get different IDs ''for cluster_obj'', but the appending to the list still changes both objects. What did i miss here? Did i understand allocation wrong? if so, wht does truly happen and how do you work around that.

Thanks in advance

Expecting 2 clusters wir 2 devices Got 2 clusters with all devices

MattDMo
  • 100,794
  • 21
  • 241
  • 231
c4lcifer
  • 3
  • 1
  • There is one `clusters` object because the default argument is only created once when the class is created (not instances of the class). Don't use mutable objects as default arguments. – Carcigenicate Nov 06 '22 at 15:41

0 Answers0