Implement MultiKeyDict class in Python with alias() method for creating aliases. Existing code fails when original key is deleted. Need fix

huangapple go评论63阅读模式
英文:

Implement MultiKeyDict class in Python with alias() method for creating aliases. Existing code fails when original key is deleted. Need fix

问题

class MultiKeyDict(dict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.aliases = {}

    def alias(self, key, alias):
        self.aliases[alias] = key

    def __getitem__(self, key):
        if key in self.aliases:
            key = self.aliases[key]
        return super().__getitem__(key)

    def __setitem__(self, key, value):
        if key in self.aliases:
            key = self.aliases[key]
        super().__setitem__(key, value)
    
    def __delitem__(self, key):
        if key in self.aliases:
            del self.aliases[key]
        super().__delitem__(key)
英文:

Python OOP problem

MultiKeyDict class, which is almost identical to the dict class. Creating an instance of MultiKeyDict class should be similar to creating an instance of dict class:

multikeydict1 = MultiKeyDict(x=1, y=2, z=3)
multikeydict2 = MultiKeyDict([('x', 1), ('y', 2), ('z', 3)])
print(multikeydict1['x']) # 1
print(multikeydict2['z']) # 3

A feature of the MultiKeyDict class should be the alias() method, which should allow aliases to be given to existing keys. The reference to the created alias should not differ from the reference to the original key, that is, the value has two keys (or more if there are several aliases) when the alias is created:

multikeydict = MultiKeyDict(x=100, y=[10, 20])

multikeydict.alias('x', 'z') # add key 'x' alias 'z'
multikeydict.alias('x', 't') # add alias 't' to key 'x'
print(multikeydict['z']) # 100
multikeydict['t'] += 1
print(multikeydict['x']) # 101

multikeydict.alias('y', 'z') # now 'z' becomes an alias of the key 'y'
multikeydict['z'] += [30]
print(multikeydict['y']) # [10, 20, 30]

The value must remain available by alias even if the original key was removed:

multikeydict = MultiKeyDict(x=100)

multikeydict.alias('x', 'z')
del multikeydict['x']
print(multikeydict['z']) # 100

Keys must take precedence over aliases. If some key and alias are the same, then all operations when accessing them must be performed with the key:

multikeydict = MultiKeyDict(x=100, y=[10, 20])

multikeydict.alias('x', 'y')
print(multikeydict['y']) # [10, 20]

I can't implement such a feature, please give me ideas how it can be done!!!

multikeydict = MultiKeyDict(x=100)

multikeydict.alias('x', 'z')
del multikeydict['x']
print(multikeydict['z']) # 100

my code does not work with this test

multikeydict = MultiKeyDict(x=100)

multikeydict.alias('x', 'z')
del multikeydict['x']
print(multikeydict['z']) #100 
class MultiKeyDict(dict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.aliases = {}

    def alias(self, key, alias):
        self.aliases[alias] = key

    def __getitem__(self, key):
        if key in self.aliases:
            key = self.aliases[key]
        return super().__getitem__(key)

    def __setitem__(self, key, value):
        if key in self.aliases:
            key = self.aliases[key]
        super().__setitem__(key, value)
    
    def __delitem__(self, key):
        if key in self.aliases:
            del self.aliases[key]
        super().__delitem__(key)


multikeydict = MultiKeyDict(x=100, y=[10, 20])

multikeydict.alias('x', 'z')
multikeydict.alias('x', 't')
print(multikeydict['z'])
multikeydict['t'] += 1
print(multikeydict['x'])

multikeydict.alias('y', 'z')
multikeydict['z'] += [30]
print(multikeydict['y'])

答案1

得分: 0

  • 正如规范所述,当键和别名同时存在时,键应具有优先权,您应该先在 self 上测试键的成员资格,然后再查看 aliases。您的方法首先检查 aliases 中的成员资格...

  • 由于在删除具有别名的键时值必须继续存在,我建议将值包装在一个列表中(该列表只包含该值作为唯一成员)。这样,您可以在别名条目中引用该列表。当删除键时,别名仍然将引用列表,并且仍然可以对其进行操作。

以下是可能的实现方式:

class MultiKeyDict(dict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.aliases = {}
        # 将每个值包装在大小为1的列表中:
        for key, value in self.items():
            super().__setitem__(key, [value])
            
    def alias(self, key, alias):
        self.aliases[alias] = super().__getitem__(key)

    def __getitem__(self, key):
        if key in self:
            return super().__getitem__(key)[0]
        return self.aliases[key][0]

    def __setitem__(self, key, value):
        if key in self:
            super().__getitem__(key)[0] = value
        elif key in self.aliases:
            self.aliases[key][0] = value
        else:
            super().__setitem__(key, [value])

    def __delitem__(self, key):
        if key in self:
            return super().__delitem__(key)
        del self.aliases[key]

请注意,以上为代码的翻译部分,没有其他内容。

英文:

Some remarks:

  • As the specification says that keys should have precedence over aliases (when both exist), you should first test key membership on self before looking in aliases. Your methods first check for membership in aliases...

  • As a value must continue to exist when a key is deleted for which there are still alias(es), I would suggest storing the values wrapped in a list (that just has that value as only member). This way you can reference that list in an alias entry. When the key is deleted, the alias will still have the reference to the list and can still act on it.

Here is how that could look:

class MultiKeyDict(dict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.aliases = {}
        # wrap each value in a list of size 1:
        for key, value in self.items():
            super().__setitem__(key, [value])
            
    def alias(self, key, alias):
        self.aliases[alias] = super().__getitem__(key)

    def __getitem__(self, key):
        if key in self:
            return super().__getitem__(key)[0]
        return self.aliases[key][0]

    def __setitem__(self, key, value):
        if key in self:
            super().__getitem__(key)[0] = value
        elif key in self.aliases:
            self.aliases[key][0] = value
        else:
            super().__setitem__(key, [value])

    def __delitem__(self, key):
        if key in self:
            return super().__delitem__(key)
        del self.aliases[key]

huangapple
  • 本文由 发表于 2023年6月2日 00:20:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76383893.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定