Search code examples
python-3.xclassdictionaryobjectnested-loops

Custom class using dictionary pythonic


In April 2019, I already make an question custom dictionary, furthermore, I already improved to like a class.

My problem now, My code is already reusable or not? because when adding new data using behavior i should repeat this one:

self.data[index] = {'weight':weight, 'visual':visual, 'step':step, 'fitness':fitness}

any suggestions and support me, please thanks a lot guys

python code, custom dictionary, and class wrapper function of dictionary in python


class Data:

  def __init__(self):
      self.data = {}

  def initial(self, index, weight, visual, step, fitness)
      self.data[index] = {'weight':weight, 'visual':visual, 'step':step, 'fitness':fitness}

  def add_following(self, index, behavior)
      self.data[index] = {'weight':weight, 'visual':visual, 'step':step, 'fitness':fitness, 'following':behavior}

  def mod_data(self, index, weight, visual, step, fitness)   
      self.data[index] = {'weight':weight, 'visual':visual, 'step':step, 'fitness':fitness}

  def del_data(self, index)
      del self.data[index]

  def __iter__(self):
    return iter(self.fish)

  def keys(self):
    return self.data.keys()

  def items(self):
    return self.data.items()

  def values(self):
    return self.data.values()

------------------------------------------------------------

import random

data = Data()

data_length = 3
weight_length = 2

visual = [random.random(0,1) for _ in range(data_length)]
weight = [[random.random(0,1) for _ in range(weight_length)] for _ in range(data_length)]
step = [random.random(0,1) for _ in range(data_length)]
behavior = [[random.random(0,1) for _ in range(weight_length)] for _ in range(data_length)]

for index in data.items():
   data.initial(index, visual[index], weight[index], step[index], fitness[index])

for beh in data.items():
   data.behavior(beh, visual[beh], weight[beh], step[beh], fitness[beh], behavior[beh])

I expected result is

0 {{'position': {'current': 0, 'target': [1, 2]}, 'weight': [0.4, 0.5], 'visual': 0.9, 'step': 0.32, 'fitness': 0.2,'following':{[0.4, 0.5], 'swarming':[0.1, 0.2]}
1 {{'position': {'current': 1, 'target': [0, 2]}, 'weight': [0.4, 0.59], 'visual': 0.3, 'step': 0.32, 'fitness': 0.2,'following':{[0.4, 0.5], 'swarming':[0.4, 0.5]}
2 {{'position': {'current': 2, 'target': [0, 1]}, 'weight': [0.41, 0.50], 'visual': 0.97, 'step': 0.75, 'fitness': 0.24,'following':{[0.42, 0.59], 'swarming':[0.21, 0.28]}

Solution

  • Based on the comments, here's one possible example you can start building on:

    Indexing by the keys 0, 1, 2, ... signalizes that list will be better structure than dict to store values.

    Here I use collections.namedtuple to create named tuple Fish with properties weight, visual, step, fitness, behavior, following. The class behaves like a tuple, so you can put it in for-loop etc. If you need more customization, I suggest making custom class.

    In a loop, I create as many Fish instances as needed - in this case data_length:

    import random
    from collections import namedtuple
    
    Fish = namedtuple('Fish', 'weight visual step fitness behavior following')
    
    data = []
    
    data_length = 3
    weight_length = 2
    
    visual = [random.random() for _ in range(data_length)]
    weight = [[random.random() for _ in range(weight_length)] for _ in range(data_length)]
    step = [random.random() for _ in range(data_length)]
    fitness = [random.random() for _ in range(data_length)]
    behavior = [[random.random() for _ in range(weight_length)] for _ in range(data_length)]
    
    for _visual, _weight, _step, _behavior, _fitness in zip(visual, weight, step, behavior, fitness):
        data.append(Fish(visual=_visual, weight=_weight, step=_step, fitness=_fitness, behavior=_behavior, following={} ))
    
    for idx, item in enumerate(data):
        print(idx, item)
    

    Prints:

    0 Fish(weight=[0.9995716623548419, 0.8374864488049845], visual=0.7545821331560755, step=0.18314419318293407, fitness=0.44659753047474804, behavior=[0.999274242465972, 0.8045066303545176], following={})
    1 Fish(weight=[0.774064177559705, 0.8007058597932238], visual=0.040803565655900376, step=0.06891491826550344, fitness=0.8789611721939403, behavior=[0.231633308916408, 0.7496932726479902], following={})
    2 Fish(weight=[0.3625792694324431, 0.46596868362347066], visual=0.20884834045098444, step=0.5649025875470652, fitness=0.27357142247178146, behavior=[0.12066601826166246, 0.3992293204074744], following={})
    

    # You can acces the date like this:
    data[0].following['some data'] = 1.234
    print(data[0])
    

    Prints:

    Fish(weight=[0.9995716623548419, 0.8374864488049845], visual=0.7545821331560755, step=0.18314419318293407, fitness=0.44659753047474804, behavior=[0.999274242465972, 0.8045066303545176], following={'some data': 1.234})