繁体   English   中英

重命名不重复的实例

[英]Rename instances without duplicates

代码是 Python,但它更像是一个我无法解决的算法问题。

我使用了一个 API,它定义了一组实例,每个实例都可以通过其Name属性访问:

print(APIClass[a_name].Name)
>>> 'a_name'
print(APIClass[another_one].Name)
>>> 'another_one'

我想(并且我被允许)重命名特定实例,但我想防止任何重复(这会导致 API 崩溃)。 如果我将示例中的第二个重命名为'a_name' ,我必须首先重命名第一个,例如:

APIClass[a_name].Name = 'a_name_old'
print(APIClass[a_name_old].Name)
>>> 'a_name_old'

没关系( APIClass[another_name] = 'a_name' )。 但我必须首先检查是否没有其他人将a_name_old作为财产,依此类推。

我应该用Name属性填充一个集合,然后重命名每个项目,然后重命名实例吗? 但是在这种情况下(我尝试过),如何确保“新”名称与旧名称不同? (在这种情况下,我在重命名实例时尝试失败)请注意,我不想删除任何重复项,只需重命名它们即可。

编辑:

提供了“APIClass”,我只是一个用户,我无法修改它们(通过添加方法等)。 我只能修改实例。 所以我想修改其中一个的“名称”属性,但我必须检查(并在需要时重命名)其他的。 如果我重命名一个,我认为我必须重新检查(并重新命名)其余部分。 所以我可以用递归算法来做,但我认为这效率不高(例如对于内存)。

是的,您应该有某种名称目录作为类变量。 此外,为 Name 属性构建一个简单的 get/set 接口,以便任何用户都可以通过它而不是直接操作名称。

您的set_name方法将检查现有名称的列表,并在建议名称已被使用时采取适当的行动。 解决冲突可能很简单,例如添加一个数字。

我不确定您对APIClass有什么限制。 但是,如果您可以实现实例名称跟踪和属性设置/删除的某种组合,那么您就可以实现您想要的。 这是一些实现这一点的代码:

class APIClass:
    instances = set()

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

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, new_name):

        assert isinstance(new_name, str)
        if new_name in self.instances:
            raise ValueError(f'Name already in use: {new_name}')

        else:
            if hasattr(self, '_name'):  # must not be first time setting name
                self.instances.remove(self._name)  # Don't forget to remove the old name before changing
            self.instances.add(new_name)
            self._name = new_name

    @name.deleter
    def name(self):
        if self._name in self.instances:
            self.instances.remove(self._name)

    def __del__(self):

        # I wont delve into why this is here. If the instance creation gets aborted due to a naming conflict,
        # Then __del__ gets called, but that leads to an attribute error, hence the try block.
        try:
            self.instances.remove(self._name)

        except AttributeError:
            pass

虽然这不是很好的做法,但它回答了您的问题。

这是它可以让您做什么的演示:

foo = APIClass('foo')
bar = APIClass('bar')
baz = APIClass('baz')

print(APIClass.instances)  # All 3 names tracked

foo.name = 'changed_foo'

print(APIClass.instances)  # Note the updated foo.name

del foo

print(APIClass.instances)  # foo.name was removed from the set

bar_2 = APIClass('bar')  # Should error since "bar" is in use

输出:

{'baz', 'bar', 'foo'}
{'changed_foo', 'baz', 'bar'}
{'baz', 'bar'}
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
# ... < long stack trace here> ...
<ValueError: Name already in use: bar

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM