簡體   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