python3:避免在字典中创建重复键

时间:2018-08-25 09:24:24

标签: python python-3.x dictionary

这是我的示例代码:

#!/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)

如您所见,我有两种将对象添加到字典的方法。尚不确定哪个更好。一个人可能更灵活地解决我的问题。因此,我将它们都包括在内。

我想建立一个反应堆及其性质的列表。

对于每个反应堆,我都会创建一个对象,该对象最终将包含该反应堆的属性(例如其体积,运行开始和结束时间等)

我想防止单元的(重复)创建。在该示例中,应避免创建值为 4 的“ reactor3”。

什么是最好的方法?在类内部,使用其中一种方法还是其他方法?

非常感谢您的见解。

3 个答案:

答案 0 :(得分:1)

只需检查项目是否已在字典的键中。仅在尚未插入时插入。

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

答案 1 :(得分:1)

如果您在某些地方更改了代码,则可以将所有创建的Unit作为类变量存储在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的所有客房清洁都由 Unit类本身,您可以集中其所属的逻辑,而不必在主程序中添加创建的单元。

建议@classmethod阅读:Meaning of @classmethod and @staticmethod for beginner?

答案 2 :(得分:0)

如果您在字典中添加具有相同键的条目,则该项将被覆盖,因此您将丢失其中的1条条目。

如果要避免这种情况,可以检查名称是否已经在字典的键值中。

怎么样?

if name in LIST_OF_UNITS.keys():
   # raise an error
else:
   pass