python3: избегайте создания дубликата ключа в словаре - PullRequest
0 голосов
/ 25 августа 2018

Вот мой пример кода:

#!/usr/bin/env python3

LIST_OF_UNITS = {}

class Unit():
    def __init__(self,name, value):
       self.name = name
       self.value = value

def create_new_unit(name, value):
    return Unit(name, value)

def add_new_unit(d, name, value):
    d[name] = Unit(name, value)
    return d

unit = create_new_unit('reactor1', 1)
LIST_OF_UNITS[unit.name] = unit

unit = create_new_unit('reactor2', 2)
LIST_OF_UNITS[unit.name] = unit

LIST_OF_UNITS = add_new_unit(LIST_OF_UNITS, 'reactor3', 3)

print(LIST_OF_UNITS)

LIST_OF_UNITS = add_new_unit(LIST_OF_UNITS, 'reactor3', 4)

print(LIST_OF_UNITS)

Как видите, у меня есть два способа добавления объектов в словарь. Еще не уверен, что лучше. Один может быть более гибким для решения моей проблемы. Итак, я включил их обоих.

Я хочу составить список реакторов и их свойств.

Для каждого реактора я создаю объект, который в конечном итоге будет содержать свойства этого реактора (например, его объем, время начала и окончания работы и т. Д.)

Я бы хотел предотвратить (дублирование) создания юнита. В этом примере следует избегать создания «реактора 3» со значением 4 .

Что было бы лучшим способом сделать это. Внутри класса, используя один из методов или как-то еще?

Ваше понимание очень ценится.

Ответы [ 3 ]

0 голосов
/ 25 августа 2018

Просто сделайте проверку, если элемент уже находится в ключах словаря. Вставьте, только если еще не там.

def add_new_unit(d, name, value):
    if(name in d.keys()):
        print("The reactor information for {name} already recorded!".format(name = name))
        return d
    d[name] = Unit(name, value)
    return d
0 голосов
/ 25 августа 2018

Если вы измените свой код вокруг некоторых, вы можете сохранить все созданные Unit s как переменную класса внутри Unit. Фабричные методы должны быть методами класса и автоматически добавлять / создавать ваши экземпляры.

class Unit():
    UNITS = {} # shared btw. instances

    def __init__(self, name, value):
        self.name = name 
        self.value = value

    # nicer output
    def __repr__(self): return "{} - {}".format(self.name, self.value)    
    def __str__(self):  return repr(self) 

# this should be a classmethod instead, depending on your usage you might want to
# raise Errors instead of returning existing instances
def create_new_unit(name, value):
    # create if needed, else return the one already in
    # does not alter Unit.value if present
    u = Unit.UNITS.setdefault(name, Unit(name,value))
    if u.value != value:
        raise ValueError("Unit '{}' exists with different value".format(name))
    else:
        return u

# this should be a classmethod instead, depending on your usage you might want to
# raise Errors instead of returning existing instances    def add_new_unit(name, value):
    # create new unit or alter an existing Unit's value
    # you should rename the method accordingly
    u = Unit.UNITS.setdefault(name, Unit(name,value)) 
    u.value = value  # change it if called again 
    return Unit.UNITS

unit1 = create_new_unit('reactor1', 1) 

unit2 = create_new_unit('reactor2', 2) 

all_units = add_new_unit('reactor3', 3)

for u in Unit.UNITS:
    print(id(Unit.UNITS[u]),Unit.UNITS[u]) 

all_units = add_new_unit('reactor3', 4)

for u in Unit.UNITS:
    print(id(Unit.UNITS[u]),Unit.UNITS[u]) 

Выход:

140125186245968 reactor1 - 1
140125186246024 reactor2 - 2
140125186246080 reactor3 - 3

140125186245968 reactor1 - 1
140125186246024 reactor2 - 2
140125186246080 reactor3 - 4 # changed by add_new_unit


# if create_new_unit(..) same named unit again with different value:
# ValueError: Unit 'reactor2' exists with different value 

Лично я бы посоветовал не создавать несколько способов создания новых. И я бы, вероятно, поместил «фабричные методы» как @classmethods, а не внутри обычной программы. Таким образом, все ведение домашнего хозяйства из Unit s осуществляется Unit сам класс, и вы можете централизовать логику, к которой он принадлежит, вместо того, чтобы добавлять созданные модули в основную программу.

Рекомендуется прочитать для @classmethod: Значение @classmethod и @staticmethod для начинающих?

0 голосов
/ 25 августа 2018

Если вы добавите запись с тем же ключом в словарь, элемент будет перезаписан, поэтому вы потеряете 1 из записей.

Если вы хотите избежать этого, вы можете проверить, если имяуже в ключевых значениях словаря.

Как насчет этого?

if name in LIST_OF_UNITS.keys():
   # raise an error
else:
   pass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...