From 312e159eeeae256135e634f2f1bc896650ad1ba7 Mon Sep 17 00:00:00 2001
From: Joseph Weston <joseph.weston08@gmail.com>
Date: Fri, 1 Apr 2016 11:39:54 +0200
Subject: [PATCH] make HoppingKind subclass of tuple

---
 kwant/builder.py            | 21 ++++++++++++++-------
 kwant/tests/test_builder.py | 10 ++++++++++
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/kwant/builder.py b/kwant/builder.py
index acdeb92d..86570a7e 100644
--- a/kwant/builder.py
+++ b/kwant/builder.py
@@ -321,7 +321,7 @@ class NoSymmetry(Symmetry):
 
 ################ Hopping kinds
 
-class HoppingKind:
+class HoppingKind(tuple):
     """A pattern for matching hoppings.
 
     A hopping ``(a, b)`` matches precisely when the site family of ``a`` equals
@@ -356,17 +356,24 @@ class HoppingKind:
         kinds = [kwant.builder.HoppingKind(v, lat) for v in [(1, 0), (0, 1)]]
         sys[kinds] = 1
     """
-    __slots__ = ('delta', 'family_a', 'family_b')
+    __slots__ = ()
+
+    delta = property(operator.itemgetter(0),
+                     doc="The difference between the tags of the hopping's sites")
+    family_a = property(operator.itemgetter(1),
+                        doc="The family of the first site in the hopping")
+    family_b = property(operator.itemgetter(2),
+                        doc="The family of the second site in the hopping")
 
-    def __init__(self, delta, family_a, family_b=None):
-        self.delta = ta.array(delta, int)
+    def __new__(cls, delta, family_a, family_b=None):
+        delta = ta.array(delta, int)
         ensure_isinstance(family_a, SiteFamily)
-        self.family_a = family_a
         if family_b is None:
-            self.family_b = family_a
+            family_b = family_a
         else:
             ensure_isinstance(family_b, SiteFamily)
-            self.family_b = family_b
+            family_b = family_b
+        return tuple.__new__(cls, (delta, family_a, family_b))
 
     def __call__(self, builder):
         delta = self.delta
diff --git a/kwant/tests/test_builder.py b/kwant/tests/test_builder.py
index 11b95c4b..85d33c55 100644
--- a/kwant/tests/test_builder.py
+++ b/kwant/tests/test_builder.py
@@ -633,6 +633,16 @@ def test_HoppingKind():
             assert sym.to_fd(a) == a
             assert_equal(a.tag - b.tag, delta)
 
+        # test hashability and equality
+        hk = builder.HoppingKind((1, 0), g)
+        hk2 = builder.HoppingKind((1, 0), g)
+        hk3 = builder.HoppingKind((1, 0), g, h)
+        assert hk == hk2
+        assert hash(hk) == hash(hk2)
+        assert hk != hk3
+        assert hash(hk) != hash(hk3)
+        assert len({hk: 0, hk2:1, hk3: 2}) == 2
+
 
 def test_ModesLead_and_SelfEnergyLead():
     lat = builder.SimpleSiteFamily()
-- 
GitLab