Joshua Bronson <jabron...@gmail.com> added the comment:

Thank you for confirming that ChainMap.__iter__() would be in the same boat as 
bidict if a similar .mapping attribute were ever added to dict_keyiterators. 
The specifics of this issue are interesting, but even more interesting to me is 
whatever learnings we can generalize from this.


After testing that the performance impact would be significant, I created the 
feature request you suggested in https://bugs.python.org/issue46713. Thanks for 
suggesting that.


In the meantime, I've updated the relevant docstrings:

>>> help(b.keys)
keys() -> KeysView[~KT] method of bidict.bidict instance
    A set-like object providing a view on the contained keys.
    
    When *b._fwdm* is a :class:`dict`, *b.keys()* returns a
    *dict_keys* object that behaves exactly the same as
    *collections.abc.KeysView(b)*, except for
    
      - offering better performance
    
      - being reversible on Python 3.8+
    
      - having a .mapping attribute in Python 3.10+
        that exposes a mappingproxy to *b._fwdm*.

>>> help(b.values)
values() -> bidict.BidictKeysView[~VT] method of bidict.bidict instance
    A set-like object providing a view on the contained values.
    
    Since the values of a bidict are equivalent to the keys of its inverse,
    this method returns a set-like object for this bidict's values
    rather than just a collections.abc.ValuesView.
    This object supports set operations like union and difference,
    and constant- rather than linear-time containment checks,
    and is no more expensive to provide than the less capable
    collections.abc.ValuesView would be.
    
    See :meth:`keys` for more information.

etc.


Regarding:
> The values() call unexpectedly returns an instance of dict_keys(). At first, 
> I was surprised that this got past the type checker -- you can do set 
> operations with KeysView but not with a ValuesView.

Check out https://github.com/jab/bidict/blob/82f931/bidict/_base.py#L38-L45:

```
class BidictKeysView(t.KeysView[KT], t.ValuesView[KT]):
    """Since the keys of a bidict are the values of its inverse (and vice 
versa),
    the ValuesView result of calling *bi.values()* is also a KeysView of 
*bi.inverse*.
    """


dict_keys: t.Type[t.KeysView[t.Any]] = type({}.keys())
BidictKeysView.register(dict_keys)
```

See also https://github.com/python/typeshed/issues/4435 for a request that 
typeshed use a Protocol (structural typing) here.


Thanks again for taking the time to look at my code and discuss so generously.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue45670>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to