95 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""Class definition for bijection."""
 | 
						|
 | 
						|
from collections import MutableMapping, Mapping
 | 
						|
 | 
						|
 | 
						|
class bijection(MutableMapping):
 | 
						|
	"""A one-to-one onto mapping, a dict with unique values."""
 | 
						|
 | 
						|
	def __init__(self, iterable=None, **kwarg):
 | 
						|
		"""Create a bijection from an iterable.
 | 
						|
 | 
						|
		Matches dict.__init__.
 | 
						|
		"""
 | 
						|
		self._data = {}
 | 
						|
		self.__inverse = self.__new__(bijection)
 | 
						|
		self.__inverse._data = {}
 | 
						|
		self.__inverse.__inverse = self
 | 
						|
		if iterable is not None:
 | 
						|
			if isinstance(iterable, Mapping):
 | 
						|
				for key, value in iterable.items():
 | 
						|
					self[key] = value
 | 
						|
			else:
 | 
						|
				for pair in iterable:
 | 
						|
					self[pair[0]] = pair[1]
 | 
						|
		for key, value in kwarg.items():
 | 
						|
			self[key] = value
 | 
						|
 | 
						|
	def __repr__(self):
 | 
						|
		if len(self._data) == 0:
 | 
						|
			return '{0}()'.format(self.__class__.__name__)
 | 
						|
		else:
 | 
						|
			repr_format = '{class_name}({values!r})'
 | 
						|
			return repr_format.format(
 | 
						|
				class_name=self.__class__.__name__,
 | 
						|
				values=self._data,
 | 
						|
				)
 | 
						|
 | 
						|
	@property
 | 
						|
	def inverse(self):
 | 
						|
		"""Return the inverse of this bijection."""
 | 
						|
		return self.__inverse
 | 
						|
 | 
						|
	# Required for MutableMapping
 | 
						|
	def __len__(self):
 | 
						|
		return len(self._data)
 | 
						|
 | 
						|
	# Required for MutableMapping
 | 
						|
	def __getitem__(self, key):
 | 
						|
		return self._data[key]
 | 
						|
 | 
						|
	# Required for MutableMapping
 | 
						|
	def __setitem__(self, key, value):
 | 
						|
		if key in self:
 | 
						|
			del self.inverse._data[self[key]]
 | 
						|
		if value in self.inverse:
 | 
						|
			del self._data[self.inverse[value]]
 | 
						|
		self._data[key] = value
 | 
						|
		self.inverse._data[value] = key
 | 
						|
 | 
						|
	# Required for MutableMapping
 | 
						|
	def __delitem__(self, key):
 | 
						|
		value = self._data.pop(key)
 | 
						|
		del self.inverse._data[value]
 | 
						|
 | 
						|
	# Required for MutableMapping
 | 
						|
	def __iter__(self):
 | 
						|
		return iter(self._data)
 | 
						|
 | 
						|
	def __contains__(self, key):
 | 
						|
		return key in self._data
 | 
						|
 | 
						|
	def clear(self):
 | 
						|
		"""Remove everything from this bijection."""
 | 
						|
		self._data.clear()
 | 
						|
		self.inverse._data.clear()
 | 
						|
 | 
						|
	def copy(self):
 | 
						|
		"""Return a copy of this bijection."""
 | 
						|
		return bijection(self)
 | 
						|
 | 
						|
	def items(self):
 | 
						|
		"""See Mapping.items."""
 | 
						|
		return self._data.items()
 | 
						|
 | 
						|
	def keys(self):
 | 
						|
		"""See Mapping.keys."""
 | 
						|
		return self._data.keys()
 | 
						|
 | 
						|
	def values(self):
 | 
						|
		"""See Mapping.values."""
 | 
						|
		return self.inverse.keys()
 | 
						|
 | 
						|
	def __eq__(self, other):
 | 
						|
		return isinstance(other, bijection) and self._data == other._data
 |