rspec/rules/S6662/python/rule.adoc
github-actions[bot] d644d018db
Create rule S6662: Set members and dictionary keys should be hashable (#2477)
You can preview this rule
[here](https://sonarsource.github.io/rspec/#/rspec/S6662/python)
(updated a few minutes after each push).

## Review

A dedicated reviewer checked the rule description successfully for:

- [ ] logical errors and incorrect information
- [ ] information gaps and missing content
- [ ] text style and tone
- [ ] PR summary and labels follow [the
guidelines](https://github.com/SonarSource/rspec/#to-modify-an-existing-rule)

---------

Co-authored-by: guillaume-dequenne-sonarsource <guillaume-dequenne-sonarsource@users.noreply.github.com>
Co-authored-by: Guillaume Dequenne <guillaume.dequenne@sonarsource.com>
2023-08-02 14:12:20 +00:00

50 lines
1.7 KiB
Plaintext

This rule raises an issue when an unhashable object is used as a set member or dictionary key.
== Why is this an issue?
The hash value of an object is an integer returned by its ``++__hash__++`` method. Objects that are considered equal to each other (as per the ``++__eq__++`` method) should have the same hash value.
Whenever using an object as a dictionary key or inserting it into a set, the hash value of that object will be used to derive a bucket in which the object will be inserted.
When attempting to insert an unhashable object into a set, a `TypeError` will be raised instead.
If an object defines a ``++__hash__++`` method derived from mutable properties, no `TypeError` will be raised. However, having a mutable hash value should never be done as this would prevent dictionaries and set from retrieving the object.
== How to fix it
Make sure to always use hashable (and immutable) objects as dictionary keys or set members.
=== Code examples
==== Noncompliant code example
[source,python,diff-id=1,diff-type=noncompliant]
----
def foo():
my_list = [1,2,3]
my_set = {my_list} # Noncompliant: list is not hashable.
----
==== Compliant solution
[source,python,diff-id=1,diff-type=compliant]
----
def foo():
my_list = [1,2,3]
my_set = set(my_list) # This will insert the elements of my_list into a new set.
# OR
def foo():
my_tuple = (1,2,3)
my_set = {my_tuple} # tuples are immutable and hashable. They can be inserted into sets.
----
== Resources
=== Documentation
* Python Documentation - https://docs.python.org/3/reference/datamodel.html#object.__hash__[object.__hash__]
* Python Documentation - https://docs.python.org/3/library/functions.html#hash[the hash built-in function]