diff --git a/modules/mol/base/doc/entity.rst b/modules/mol/base/doc/entity.rst
index 173ea4a9296c87a2f96345d1857aa9edf3b3189a..657125a2fa11c289dcfb3339d22cfdae4ccd561a 100644
--- a/modules/mol/base/doc/entity.rst
+++ b/modules/mol/base/doc/entity.rst
@@ -484,6 +484,15 @@ The Handle Classes
 
      :type: :class:`ChainType`.
 
+  .. attribute:: hash_code
+
+    A unique identifier for this chain. Note that a deep copy of an entity (see
+    :meth:`EntityHandle.Copy`) will have chains with differing identifiers.
+    Shallow copies of the entity preserve the identifier.
+    Also available as :meth:`GetHashCode`.
+
+    :type: int
+
   .. attribute:: valid
 
     Validity of handle.
@@ -558,6 +567,12 @@ The Handle Classes
 
     See :attr:`description`
 
+  .. method:: GetHashCode()
+
+    See :attr:`hash_code`
+
+    :rtype: int
+
   .. method:: IsValid()
   
     See :attr:`valid`
@@ -784,6 +799,15 @@ The Handle Classes
 
     :type: :class:`~ost.geom.Vec3`
 
+  .. attribute:: hash_code
+
+    A unique identifier for this residue. Note that a deep copy of an entity (see
+    :meth:`EntityHandle.Copy`) will have residues with differing identifiers.
+    Shallow copies of the entity preserve the identifier. Also available as
+    :meth:`GetHashCode`.
+
+    :type: int
+
   .. attribute:: valid
 
     Validity of handle.
@@ -959,6 +983,12 @@ The Handle Classes
     
     See :attr:`central_normal`
 
+  .. method:: GetHashCode()
+
+    See :attr:`hash_code`
+
+    :rtype: int
+
   .. method:: IsValid()
   
     See :attr:`valid`
@@ -1099,7 +1129,8 @@ The Handle Classes
     :meth:`EntityHandle.Copy`) will have atoms with differing identifiers.
     Shallow copies of the entity preserve the identifier. Atom views on a handle
     have different identifiers, but the atom view handles (see
-    :attr:`AtomView.handle`) have the same identifier.
+    :attr:`AtomView.handle`) have the same identifier. Also available
+    as :meth:`GetHashCode`.
 
     :type: int
 
@@ -1331,7 +1362,7 @@ The View Classes
 .. class:: EntityView
 
   An entity view represents a structural subset of an :class:`EntityHandle`. For 
-  an introduction ,see :doc:`../../intro-01`.
+  an introduction, see :doc:`../../intro-01`.
 
   .. attribute:: handle
 
@@ -1703,6 +1734,14 @@ The View Classes
 
     :type: :class:`ChainHandle`
 
+  .. attribute:: hash_code
+
+    A unique identifier for this chain view. Note, that this is not the same as
+    for the chain handle (see :attr:`ChainHandle.hash_code`).
+    Also available as :meth:`GetHashCode`.
+
+    :type: int
+
   .. attribute:: name
   
      The chain name. The name uniquely identifies the chain in the entity. In
@@ -1863,6 +1902,10 @@ The View Classes
 
     See :attr:`handle`
 
+  .. method:: GetHashCode()
+    
+    See :attr:`hash_code`
+
   .. method:: GetMass()
 
     See :attr:`mass`
@@ -1927,6 +1970,14 @@ The View Classes
 
     :type: :class:`ResidueHandle`
 
+  .. attribute:: hash_code
+
+    A unique identifier for this residue view. Note, that this is not the same as
+    for the residue handle (see :attr:`ResidueHandle.hash_code`).
+    Also available as :meth:`GetHashCode`.
+
+    :type: int
+
   .. attribute:: name
                  qualified_name
                  number
@@ -1994,6 +2045,10 @@ The View Classes
 
     See :attr:`handle`
 
+  .. method:: GetHashCode()
+    
+    See :attr:`hash_code`
+
   .. method:: GetName
               GetQualifiedName
               GetNumber
@@ -2093,6 +2148,7 @@ The View Classes
 
     A unique identifier for this atom view. Note, that this is not the same as
     for the atom handle (see :attr:`AtomHandle.hash_code`).
+    Also available as :meth:`GetHashCode`.
 
     :type: int
 
diff --git a/modules/mol/base/pymod/export_chain.cc b/modules/mol/base/pymod/export_chain.cc
index b5ce6d91cba30b6a3dab3a83a066f044139e1d41..d358cc19883b7a867620475db820858c2ad26d6d 100644
--- a/modules/mol/base/pymod/export_chain.cc
+++ b/modules/mol/base/pymod/export_chain.cc
@@ -116,6 +116,9 @@ void export_Chain()
     .def("GetGeometricEnd", geom_end<ChainHandle>)
     .def(self==self)
     .def(self!=self)
+    .def("__hash__", &ChainHandle::GetHashCode)
+    .def("GetHashCode", &ChainHandle::GetHashCode)
+    .add_property("hash_code", &ChainHandle::GetHashCode)
   ;
   
   class_<ChainHandleList>("ChainHandleList", no_init)
diff --git a/modules/mol/base/pymod/export_chain_view.cc b/modules/mol/base/pymod/export_chain_view.cc
index 3587cc57294cbee62aeab82f9bbde471a56ff3e6..7c68ee8f1f459dd9c6c98b440b4497d1cde82281 100644
--- a/modules/mol/base/pymod/export_chain_view.cc
+++ b/modules/mol/base/pymod/export_chain_view.cc
@@ -113,6 +113,9 @@ void export_ChainView()
     .add_property("bounds", &ChainView::GetBounds)
     .def(self==self)
     .def(self!=self)
+    .def("__hash__", &ChainView::GetHashCode)
+    .def("GetHashCode", &ChainView::GetHashCode)
+    .add_property("hash_code", &ChainView::GetHashCode)
   ;
 
 
diff --git a/modules/mol/base/pymod/export_residue_view.cc b/modules/mol/base/pymod/export_residue_view.cc
index 9d14320de594bb3220792085258551f9e1d82cbe..62b8ac413c02cd509300f9c946a3fc41141357c8 100644
--- a/modules/mol/base/pymod/export_residue_view.cc
+++ b/modules/mol/base/pymod/export_residue_view.cc
@@ -94,7 +94,10 @@ void export_ResidueView()
     .def("GetGeometricStart", geom_start<ResidueView>)
     .def("GetGeometricEnd", geom_end<ResidueView>) 
     .def("GetBounds", &ResidueView::GetBounds)
-    .add_property("bounds", &ResidueView::GetBounds)    
+    .add_property("bounds", &ResidueView::GetBounds)
+    .def("__hash__", &ResidueView::GetHashCode)
+    .def("GetHashCode", &ResidueView::GetHashCode)
+    .add_property("hash_code", &ResidueView::GetHashCode)
   ;
 
 
diff --git a/modules/mol/base/src/atom_handle.cc b/modules/mol/base/src/atom_handle.cc
index 25eba43f8feea064693e91fe31c1e65b50593b57..ae3bcf9206a595f2a797a50bfd2be7a8828c461e 100644
--- a/modules/mol/base/src/atom_handle.cc
+++ b/modules/mol/base/src/atom_handle.cc
@@ -116,10 +116,10 @@ AtomHandle AtomHandle::GetHandle() const
   return *this;
 }
 
-long AtomHandle::GetHashCode() const 
+unsigned long AtomHandle::GetHashCode() const
 {
   this->CheckValidity();  
-  return reinterpret_cast<long>(Impl().get());
+  return reinterpret_cast<unsigned long>(Impl().get());
 }
 
 }} // ns
diff --git a/modules/mol/base/src/atom_handle.hh b/modules/mol/base/src/atom_handle.hh
index 1dbdf09d5a3d7495fbe8eb5244ff9f986dca66e1..fca1922e908f77cf736e2ea2b681167fd9f38be2 100644
--- a/modules/mol/base/src/atom_handle.hh
+++ b/modules/mol/base/src/atom_handle.hh
@@ -87,7 +87,7 @@ public:
   /// 
   /// Get hash code that uniquely identifies every atom. The hash code is
   /// identical for all atom views pointing to a given atom.
-  long GetHashCode() const;
+  unsigned long GetHashCode() const;
   
   bool operator==(const AtomHandle& ref) const;
   bool operator!=(const AtomHandle& ref) const;
diff --git a/modules/mol/base/src/atom_view.cc b/modules/mol/base/src/atom_view.cc
index 2bd424c8e8947f686f08c72bb50e98c3d7bd23be..5fcb7010abbdf1dd20d31e8f104f26accd0f5f15 100644
--- a/modules/mol/base/src/atom_view.cc
+++ b/modules/mol/base/src/atom_view.cc
@@ -161,10 +161,10 @@ void AtomView::RemoveBondInternal(const BondHandle& bond)
   }
 }
 
-long AtomView::GetHashCode() const 
+unsigned long AtomView::GetHashCode() const
 {
   this->CheckValidity();  
-  return reinterpret_cast<long>(data_.get());
+  return reinterpret_cast<unsigned long>(data_.get());
 } 
 
 }} // ns
diff --git a/modules/mol/base/src/atom_view.hh b/modules/mol/base/src/atom_view.hh
index a853669c1ea0dec9569732c486d6ca2b3b92ff3a..2172453937cddc59c70b4a2439a7129e83d749a2 100644
--- a/modules/mol/base/src/atom_view.hh
+++ b/modules/mol/base/src/atom_view.hh
@@ -87,7 +87,7 @@ public:
   /// 
   /// The unique id is the same for all AtomViews pointing to the same atom 
   /// view data. 
-  long GetHashCode() const;
+  unsigned long GetHashCode() const;
   bool operator==(const AtomView& rhs) const;
   bool operator!=(const AtomView& rhs) const;
 protected:
diff --git a/modules/mol/base/src/bond_handle.cc b/modules/mol/base/src/bond_handle.cc
index 9dd04ca1220d35e779026f4654c5a5854b5ebc50..f9c95d6887f8858c8a28bb5203b300a94e8ff376 100644
--- a/modules/mol/base/src/bond_handle.cc
+++ b/modules/mol/base/src/bond_handle.cc
@@ -122,6 +122,7 @@ void BondHandle::Apply(EntityViewVisitor& v)
 
 unsigned long BondHandle::GetHashCode() const
 {
+  this->CheckValidity();
   return reinterpret_cast<unsigned long>(impl_.get());
 }
 
diff --git a/modules/mol/base/src/chain_handle.cc b/modules/mol/base/src/chain_handle.cc
index 5ecc5c1fbdd5fe19d348d1136b88e8116feb6665..bef637465b7fc2e7dffa3e0eb81dcdb986832af6 100644
--- a/modules/mol/base/src/chain_handle.cc
+++ b/modules/mol/base/src/chain_handle.cc
@@ -205,6 +205,7 @@ void ChainHandle::SetInSequence(const int index)
 
 unsigned long ChainHandle::GetHashCode() const
 {
+  this->CheckValidity();
   return reinterpret_cast<unsigned long>(Impl().get());
 }
 
diff --git a/modules/mol/base/src/chain_view.cc b/modules/mol/base/src/chain_view.cc
index e0c5b5dce051f82ec27f705cfb0ebf07deec7c7f..c8498b1d38099efa32454fb9159fa4a3f2a057a1 100644
--- a/modules/mol/base/src/chain_view.cc
+++ b/modules/mol/base/src/chain_view.cc
@@ -477,5 +477,11 @@ bool ChainView::HasAtoms() const {
   return false;
 }
 
+unsigned long ChainView::GetHashCode() const
+{
+  this->CheckValidity();
+  return reinterpret_cast<unsigned long>(data_.get());
+}
+
 }} // ns
 
diff --git a/modules/mol/base/src/chain_view.hh b/modules/mol/base/src/chain_view.hh
index c107261d3c7d4475969ccb4c0a98e8dffb3ec268..6f2c1a337042d83cb24e85d4c796683a343d6ba2 100644
--- a/modules/mol/base/src/chain_view.hh
+++ b/modules/mol/base/src/chain_view.hh
@@ -196,6 +196,12 @@ public:
   /// \brief return view based on query String.
   /// \sa Query
   EntityView Select(const String& query_string, QueryFlags flags=0) const;
+
+  /// \brief get unique id
+  ///
+  /// The unique id is the same for all ChainViews pointing to the same chain
+  /// view data.
+  unsigned long GetHashCode() const;
     
   bool operator==(const ChainView& rhs) const;
   bool operator!=(const ChainView& rhs) const;
diff --git a/modules/mol/base/src/residue_handle.cc b/modules/mol/base/src/residue_handle.cc
index a355f7fcfa519cfe2186e236a70750b92e954bb4..ee0a8d0c1b529de874eed1119a68bee3ccc8ea53 100644
--- a/modules/mol/base/src/residue_handle.cc
+++ b/modules/mol/base/src/residue_handle.cc
@@ -210,6 +210,7 @@ double ResidueHandle::GetMass() const
 
 unsigned long ResidueHandle::GetHashCode() const
 {
+  this->CheckValidity();
   return reinterpret_cast<unsigned long>(Impl().get());
 }
 
diff --git a/modules/mol/base/src/residue_view.cc b/modules/mol/base/src/residue_view.cc
index db550340700e16951cd1dc5a5ca3a6bb0a13c86e..5948a38a479887b76fedc47f85ce76a80951c0f3 100644
--- a/modules/mol/base/src/residue_view.cc
+++ b/modules/mol/base/src/residue_view.cc
@@ -285,4 +285,10 @@ bool ResidueView::HasAtoms() const {
   return data_->atoms.size()>0;
 }
 
+unsigned long ResidueView::GetHashCode() const
+{
+  this->CheckValidity();
+  return reinterpret_cast<unsigned long>(data_.get());
+}
+
 }} //ns
diff --git a/modules/mol/base/src/residue_view.hh b/modules/mol/base/src/residue_view.hh
index 518de3f1ab5a2ba72722e99377458acbe34d7e17..8268143fa34bdeead462dba753a71c640b83946b 100644
--- a/modules/mol/base/src/residue_view.hh
+++ b/modules/mol/base/src/residue_view.hh
@@ -178,6 +178,12 @@ public:
   /// \brief return view based on query String.
   /// \sa Query
   EntityView Select(const String& query_string, QueryFlags flags=0) const;
+
+  /// \brief get unique id
+  ///
+  /// The unique id is the same for all ResidueViews pointing to the same residue
+  /// view data.
+  unsigned long GetHashCode() const;
   
   bool operator==(const ResidueView& rhs) const;
   
diff --git a/modules/mol/base/tests/test_residue.cc b/modules/mol/base/tests/test_residue.cc
index 17ef6ee59fd3d648794e9aba33be9d73554866f7..1da38c3e35d9a92400815d4bcc5959bc3d77e328 100644
--- a/modules/mol/base/tests/test_residue.cc
+++ b/modules/mol/base/tests/test_residue.cc
@@ -88,6 +88,35 @@ BOOST_AUTO_TEST_CASE(throw_invalid_res_view)
   BOOST_CHECK_NO_THROW(CheckHandleValidity(res));
 }
 
+// Test that .GetHashCode() throws on invalid residue handle
+BOOST_AUTO_TEST_CASE(throw_hash_code_invalid_res_handle)
+{
+  ChainHandle chain;
+  EntityHandle ent=CreateEntity();
+  XCSEditor edi=ent.EditXCS();
+  chain=edi.InsertChain("A");
+  ResidueHandle res=chain.FindResidue(ResNum(1));
+  BOOST_CHECK_THROW(res.GetHashCode(), InvalidHandle);
+  edi.AppendResidue(chain, "GLY");
+  res=chain.FindResidue(ResNum(1));
+  BOOST_CHECK_NO_THROW(res.GetHashCode());
+}
+
+// Test that .GetHashCode() throws on invalid residue views
+BOOST_AUTO_TEST_CASE(throw_hash_code_invalid_res_view)
+{
+  ChainHandle chain;
+  EntityHandle ent=CreateEntity();
+  XCSEditor edi=ent.EditXCS();
+  chain=edi.InsertChain("A");
+  ResidueView res;
+  BOOST_CHECK_THROW(res.GetHashCode(), InvalidHandle);
+  edi.AppendResidue(chain, "GLY");
+  EntityView ent_view=ent.CreateFullView();
+  res=ent_view.FindChain("A").FindResidue(1);
+  BOOST_CHECK_NO_THROW(res.GetHashCode());
+}
+
 BOOST_AUTO_TEST_CASE(test_res_index)
 {
   EntityHandle eh=CreateEntity();