[Tutor] Mutable objects as dictionary keys: Accessing , Sorting and Using dictionary

Steven D'Aprano steve at pearwood.info
Fri Apr 19 00:26:09 EDT 2019


On Thu, Apr 18, 2019 at 11:18:02AM -0400, Pushkar vaity wrote:
> Hi,
> 
> I am using Python 3.7 with anaconda install in PyCharm
> I am trying to traverse some directories using the os module and grab some
> tcl procedures and put the proc names in python dictionary as keys. Values
> are some other info related to the proc.
> 
> Problem: procs found in the directories can have similar names. But python
> dict keys cannot be same.

Sorry, can you explain why this is a problem? *Similar* is not 
enough to cause keys to clash. If you have a proc name "abcd" and a 
similar name "abcd.1", they count as different keys.

Could you use the full pathname?

    "/some/directory/proc.123"

    "/another/directory/proc.123"

would count as different keys.


> So I am using the mutable objects as the key.
> 
> For Ex:   class MyClass:
> 
>     def __init__(self, name):
>         self.name = name
> 
>     def __repr__(self):
>         return repr(self.name)

I'm not convinced that you actually need this class, but if you do, you 
ought to define a hash method:

    def __hash__(self):
        return hash(self.name)

and equality:

    def __eq__(self, other):
        if isinstance(other, MyClass):
            return self.name == other.name
        return NotImplemented


otherwise dict lookups will be by object identity, not value.


> proc_dict[MyClass(proc_name)] = (full_file, proc_args)
> 
> This has allowed me to have same separate keys in my dictionary.
> But now,
> 
>    1. I am not able to access individual dictionary values by
> specifying only the key name.

Add the __hash__ and __eq__ methods as above, and then try:


    values = proc_dict[ MyClass(proc_name) ]


>    2. I am not able to use the 'in' or 'not in' operations on my
> dictionary successfully.

Again, you need __hash__ and __eq__ for them to work correctly.


>    3. Also, I am not able to use the sorted() function on my dict
> items. It gives me an error as follows:
> 
> 
>    - for proc_name, (file_name, proc_args) in sorted(proc_dict.items()):
>       - TypeError: '<' not supported between instances of 'MyClass'
> and 'MyClass'

You need to define a __lt__ method:

    def __lt__(self, other):
        if isinstance(other, MyClass):
            return self.name < other.name
        return NotImplemented


But again, I'm not convinced that you need this class at all. Can you 
please show us the proc names you get, how you get them, and what you do 
with them?

Using a wrapper class like this is probably the last resort.



-- 
Steven


More information about the Tutor mailing list