Skip to main content
added 63 characters in body
Source Link

As explained in Greg's answer, optimization-wise, there is nothing to worry about.

Now, regarding the maintainability problem (i.e. having to keep two copies of the same data in sync), a solution would be to use references to the object's ID/name field as keys to the associative container, if the language allows it.

Note that since strings are usually immutable objects, one may need to wrap them in a mutable object and store a reference to that instead. The Python example shown in the question is wrong; this would be a possible correct version:

# class of objects that need ID or name
class MyClass:
    # mutable class to wrap the immutable string value
    class Name:
        def __init__(self, value: str):
            self.value = value
        
        # enable direct string comparisons
        def __eq__(self, other): return self.value == other
        def __le__(self, other): return self.value < other
        def __hash__(self): return hash(self.value)

    def __init__(self, name: str):
        self._name = MyClass.Name(name)
    
    @property
    def name(self) -> str:
        return self._name.value

    @name.setter
    def name(self, value: str):
        self._name.value = value


# associative container from names to objects
my_instances = {}[]

# add an object
obj = MyClass("Bob")
my_instances[objmy_instances.name] =append((obj._name, obj))  # use wrapper object as key

# retrieve an object
print(my_instances["Bob"]next(o for n, o in my_instances if n == "Bob"))

# change an object's name
obj.name = "Tony"
print(my_instances["Tony"]next(o for n, o in my_instances if n == "Tony"))  # works fine

As explained in Greg's answer, optimization-wise, there is nothing to worry about.

Now, regarding the maintainability problem (i.e. having to keep two copies of the same data in sync), a solution would be to use references to the object's ID/name field as keys to the associative container, if the language allows it.

Note that since strings are usually immutable objects, one may need to wrap them in a mutable object and store a reference to that instead. The Python example shown in the question is wrong; this would be a possible correct version:

# class of objects that need ID or name
class MyClass:
    # mutable class to wrap the immutable string value
    class Name:
        def __init__(self, value: str):
            self.value = value
        
        # enable direct string comparisons
        def __eq__(self, other): return self.value == other
        def __le__(self, other): return self.value < other
        def __hash__(self): return hash(self.value)

    def __init__(self, name: str):
        self._name = MyClass.Name(name)
    
    @property
    def name(self) -> str:
        return self._name.value

    @name.setter
    def name(self, value: str):
        self._name.value = value


# associative container from names to objects
my_instances = {}

# add an object
obj = MyClass("Bob")
my_instances[obj.name] = obj
print(my_instances["Bob"])

# change an object's name
obj.name = "Tony"
print(my_instances["Tony"])  # works fine

As explained in Greg's answer, optimization-wise, there is nothing to worry about.

Now, regarding the maintainability problem (i.e. having to keep two copies of the same data in sync), a solution would be to use references to the object's ID/name field as keys to the associative container, if the language allows it.

Note that since strings are usually immutable objects, one may need to wrap them in a mutable object and store a reference to that instead. The Python example shown in the question is wrong; this would be a possible correct version:

# class of objects that need ID or name
class MyClass:
    # mutable class to wrap the immutable string value
    class Name:
        def __init__(self, value: str):
            self.value = value
        
        # enable direct string comparisons
        def __eq__(self, other): return self.value == other
        def __le__(self, other): return self.value < other

    def __init__(self, name: str):
        self._name = MyClass.Name(name)
    
    @property
    def name(self) -> str:
        return self._name.value

    @name.setter
    def name(self, value: str):
        self._name.value = value


# associative container from names to objects
my_instances = []

# add an object
obj = MyClass("Bob")
my_instances.append((obj._name, obj))  # use wrapper object as key

# retrieve an object
print(next(o for n, o in my_instances if n == "Bob"))

# change an object's name
obj.name = "Tony"
print(next(o for n, o in my_instances if n == "Tony"))  # works fine
Source Link

As explained in Greg's answer, optimization-wise, there is nothing to worry about.

Now, regarding the maintainability problem (i.e. having to keep two copies of the same data in sync), a solution would be to use references to the object's ID/name field as keys to the associative container, if the language allows it.

Note that since strings are usually immutable objects, one may need to wrap them in a mutable object and store a reference to that instead. The Python example shown in the question is wrong; this would be a possible correct version:

# class of objects that need ID or name
class MyClass:
    # mutable class to wrap the immutable string value
    class Name:
        def __init__(self, value: str):
            self.value = value
        
        # enable direct string comparisons
        def __eq__(self, other): return self.value == other
        def __le__(self, other): return self.value < other
        def __hash__(self): return hash(self.value)

    def __init__(self, name: str):
        self._name = MyClass.Name(name)
    
    @property
    def name(self) -> str:
        return self._name.value

    @name.setter
    def name(self, value: str):
        self._name.value = value


# associative container from names to objects
my_instances = {}

# add an object
obj = MyClass("Bob")
my_instances[obj.name] = obj
print(my_instances["Bob"])

# change an object's name
obj.name = "Tony"
print(my_instances["Tony"])  # works fine