[英]Rename instances without duplicates
The code is Python, but it's more an algorithmic question I can't solve.代码是 Python,但它更像是一个我无法解决的算法问题。
I use an API which defines a set of instances, each one is reachable by its Name
property:我使用了一个 API,它定义了一组实例,每个实例都可以通过其
Name
属性访问:
print(APIClass[a_name].Name)
>>> 'a_name'
print(APIClass[another_one].Name)
>>> 'another_one'
I want (and I'm allowed) to rename a specific instance, but I want to prevent any duplicate (which leads to an API crash).我想(并且我被允许)重命名特定实例,但我想防止任何重复(这会导致 API 崩溃)。 If I rename the second in my example to
'a_name'
, I have first to rename the first one, eg:如果我将示例中的第二个重命名为
'a_name'
,我必须首先重命名第一个,例如:
APIClass[a_name].Name = 'a_name_old'
print(APIClass[a_name_old].Name)
>>> 'a_name_old'
and it's OK ( APIClass[another_name] = 'a_name'
).没关系(
APIClass[another_name] = 'a_name'
)。 But I have to check first that no one else has a_name_old
as property, and so on.但我必须首先检查是否没有其他人将
a_name_old
作为财产,依此类推。
Should I populate a set with the Name
properties, then rename each item, and then rename the instances?我应该用
Name
属性填充一个集合,然后重命名每个项目,然后重命名实例吗? But in this case (I tried it), how to be sure that a 'new' name will not be the same that an old one?但是在这种情况下(我尝试过),如何确保“新”名称与旧名称不同? (in this case, my tries failed when renaming instances) Please note I don't want to remove any duplicates, just rename them.
(在这种情况下,我在重命名实例时尝试失败)请注意,我不想删除任何重复项,只需重命名它们即可。
EDIT:编辑:
The 'APIClass' are provided, I'm only a user and I can't modify them (by adding methods, or so on).提供了“APIClass”,我只是一个用户,我无法修改它们(通过添加方法等)。 I can only modify instances.
我只能修改实例。 So I want to modify the 'Name' property of one of them, but I have to check (and rename if needed) the other ones.
所以我想修改其中一个的“名称”属性,但我必须检查(并在需要时重命名)其他的。 If I rename one, in my opinion I have to re-check (and re-rename) the remainings.
如果我重命名一个,我认为我必须重新检查(并重新命名)其余部分。 So I could do it with a recursive algorithm, but I thought this is not efficient (for memory eg).
所以我可以用递归算法来做,但我认为这效率不高(例如对于内存)。
Yes, you should have some sort of name directory as a class variable.是的,您应该有某种名称目录作为类变量。 Also, build a simple get/set interface for the Name property, so that any user will go through that instead of directly manipulating the name.
此外,为 Name 属性构建一个简单的 get/set 接口,以便任何用户都可以通过它而不是直接操作名称。
Your set_name
method will check the list of existing names and act appropriately if the suggested name is already in use.您的
set_name
方法将检查现有名称的列表,并在建议名称已被使用时采取适当的行动。 Resolving a collision can be simple, such as appending a number.解决冲突可能很简单,例如添加一个数字。
I'm not sure what limitations you have on your APIClass
.我不确定您对
APIClass
有什么限制。 However, if you can implement some combination of instance name tracking and property setting/deleting then you can achieve what you want.但是,如果您可以实现实例名称跟踪和属性设置/删除的某种组合,那么您就可以实现您想要的。 Here is some code that implements just that:
这是一些实现这一点的代码:
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
While this isn't great practice, it answers your question.虽然这不是很好的做法,但它回答了您的问题。
Here's a demo of what it lets you do:这是它可以让您做什么的演示:
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
output:输出:
{'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.