code: def find(self, bs, start=None, end=None, bytealigned=None):
          
          bs = Bits(bs)
          if not bs.len:
              raise ValueError("Cannot find an empty bitstring.")
          start, end = self._validate_slice(start, end)
          if bytealigned is None:
              bytealigned = globals()['bytealigned']
          if bytealigned and not bs.len % 8 and not self._datastore.offset:
              p = self._findbytes(bs.bytes, start, end, bytealigned)
          else:
              p = self._findregex(re.compile(bs._getbin()), start, end, bytealigned)
          # If called from a class that has a pos, set it
          try:
              self._pos = p[0]
          except (AttributeError, IndexError):
              pass
          return p
docs: Find first occurrence of substring bs.
  
          Returns a single item tuple with the bit position if found, or an
          empty tuple if not found. The bit position (pos property) will
          also be set to the start of the substring if it is found.
  
          bs -- The bitstring to find.
          start -- The bit position to start the search. Defaults to 0.
          end -- The bit position one past the last bit to search.
                 Defaults to self.len.
          bytealigned -- If True the bitstring will only be
                         found on byte boundaries.
  
          Raises ValueError if bs is empty, if start < 0, if end > self.len or
          if end < start.
  
          >>> BitArray('0xc3e').find('0b1111')
          (6,)