ó
ËĢ,]c           @   sU   d  d l  m Z m Z m Z d  d l m Z m Z d e f d     YZ d   Z	 d S(   iĸĸĸĸ(   t   gettert   const   pluck(   t   teet   starmapt   EqualityHashKeyc           B   sV   e  Z d  Z d d g Z d Z d   Z d   Z d   Z d   Z d   Z	 d	   Z
 RS(
   sī   Create a hash key that uses equality comparisons between items.

    This may be used to create hash keys for otherwise unhashable types:

    >>> from toolz import curry
    >>> EqualityHashDefault = curry(EqualityHashKey, None)
    >>> set(map(EqualityHashDefault, [[], (), [1], [1]]))  # doctest: +SKIP
    {=[]=, =()=, =[1]=}

    **Caution:** adding N ``EqualityHashKey`` items to a hash container
    may require O(N**2) operations, not O(N) as for typical hashable types.
    Therefore, a suitable key function such as ``tuple`` or ``frozenset``
    is usually preferred over using ``EqualityHashKey`` if possible.

    The ``key`` argument to ``EqualityHashKey`` should be a function or
    index that returns a hashable object that effectively distinguishes
    unequal items.  This helps avoid the poor scaling that occurs when
    using the default key.  For example, the above example can be improved
    by using a key function that distinguishes items by length or type:

    >>> EqualityHashLen = curry(EqualityHashKey, len)
    >>> EqualityHashType = curry(EqualityHashKey, type)  # this works too
    >>> set(map(EqualityHashLen, [[], (), [1], [1]]))  # doctest: +SKIP
    {=[]=, =()=, =[1]=}

    ``EqualityHashKey`` is convenient to use when a suitable key function
    is complicated or unavailable.  For example, the following returns all
    unique values based on equality:

    >>> from toolz import unique
    >>> vals = [[], [], (), [1], [1], [2], {}, {}, {}]
    >>> list(unique(vals, key=EqualityHashDefault))
    [[], (), [1], [2], {}]

    **Warning:** don't change the equality value of an item already in a hash
    containter.  Unhashable types are unhashable for a reason.  For example:

    >>> L1 = [1] ; L2 = [2]
    >>> s = set(map(EqualityHashDefault, [L1, L2]))
    >>> s  # doctest: +SKIP
    {=[1]=, =[2]=}

    >>> L1[0] = 2  # Don't do this!  ``s`` now has duplicate items!
    >>> s  # doctest: +SKIP
    {=[2]=, =[2]=}

    Although this may appear problematic, immutable data types is a common
    idiom in functional programming, and``EqualityHashKey`` easily allows
    the same idiom to be used by convention rather than strict requirement.

    See Also:
        identity
    t   itemt   keyt   __default__hashkey__c         C   sO   | d  k r |  j |  _ n' t |  s9 t |  |  _ n	 | |  _ | |  _ d  S(   N(   t   Nonet   _default_hashkeyR   t   callableR    R   (   t   selfR   R   (    (    s1   lib/python2.7/site-packages/toolz/sandbox/core.pyt   __init__@   s    	c         C   s:   |  j  |  j k r |  j  } n |  j  |  j  } t |  S(   N(   R   R
   R   t   hash(   R   t   val(    (    s1   lib/python2.7/site-packages/toolz/sandbox/core.pyt   __hash__I   s    c         C   s?   y& |  j  | j  k o$ |  j | j k SWn t k
 r: t SXd  S(   N(   R
   R   t   AttributeErrort   False(   R   t   other(    (    s1   lib/python2.7/site-packages/toolz/sandbox/core.pyt   __eq__P   s
    c         C   s   |  j  |  S(   N(   R   (   R   R   (    (    s1   lib/python2.7/site-packages/toolz/sandbox/core.pyt   __ne__W   s    c         C   s   d t  |  j  S(   Ns   =%s=(   t   strR   (   R   (    (    s1   lib/python2.7/site-packages/toolz/sandbox/core.pyt   __str__Z   s    c         C   s   d t  |  j  S(   Ns   =%s=(   t   reprR   (   R   (    (    s1   lib/python2.7/site-packages/toolz/sandbox/core.pyt   __repr__]   s    (   t   __name__t
   __module__t   __doc__t	   __slots__R
   R   R   R   R   R   R   (    (    (    s1   lib/python2.7/site-packages/toolz/sandbox/core.pyR      s   5						c         C   sw   t  |   }  y t t |    } Wn t k
 r9 t   SXt |  } t t | |   |  } t t t t	 |    S(   sJ  Inverse of ``zip``

    >>> a, b = unzip([('a', 1), ('b', 2)])
    >>> list(a)
    ['a', 'b']
    >>> list(b)
    [1, 2]

    Unlike the naive implementation ``def unzip(seq): zip(*seq)`` this
    implementation can handle an infinite sequence ``seq``.

    Caveats:

    * The implementation uses ``tee``, and so can use a significant amount
      of auxiliary storage if the resulting iterators are consumed at
      different times.

    * The inner sequence cannot be infinite. In Python 3 ``zip(*seq)`` can be
      used if ``seq`` is a finite sequence of infinite sequences.

    (
   t   itert   tuplet   nextt   StopIterationt   lenR   R   R   R   t	   enumerate(   t   seqt   firstt   niterst   seqs(    (    s1   lib/python2.7/site-packages/toolz/sandbox/core.pyt   unzipb   s    N(
   t   toolz.itertoolzR    R   R   t	   itertoolsR   R   t   objectR   R(   (    (    (    s1   lib/python2.7/site-packages/toolz/sandbox/core.pyt   <module>   s   [