On Mon, Dec 28, 2020 at 3:54 AM Steven D'Aprano <st...@pearwood.info> wrote:

> > Steven D'Aprano wrote:
> > > Why do you want something that isn't a mapping to be usable with
> mapping
> > > unpacking?
> >
> > I think mapping is not `abc.Mapping` class only.
>
> You don't have to inherit from Mapping for this to work. Double-star
> unpacking already supports duck-typing:
>
> >>> class MyMapping:
> ...     def keys(self):
> ...             return iter('abc')
> ...     def __getitem__(self, key):
> ...             if key in ('a', 'b', 'c'):
> ...                     return key.upper()
> ...             raise KeyError
> ...
> >>> def demo(**kwargs):
> ...     print(kwargs)
>

Thanks! this would have shortcutted this conversation if it come earlier.
The OP, and me, took the error message at its word, and also, in
experimenting, didn't happen on the right part of the Mapping API that
needed to be supported.

I don't know about the OP, but all I wanted was a clear definition of the
part of the API needed to support **, and apparently it's a keys() method
that returns an iterator of the keys, and a __getitem__ that then returns
the values associated with those keys. Which is fine.

Though frankly, I would rather have had it use .items() -- seems more
efficient to me, and you do need both the keys and the values, and items()
is just as much part of the Mapping API as keys.

But there is an argument that the ** operator should be able to be
supported only with dunder methods -- which could be done if it used the
iterator protocol to get the keys, rather than the keys() method, which
does not appear to work now. though to be fair, all you need to do to get
that is add a __len__ and derive from Mapping.

and to the OP's question a decorator that makes a Mapping from a dataclass
would be pretty easy to write.

-CHB


> >>> import collections.abc
> >>> issubclass(MyMapping, collections.abc.Mapping)
> False
> >>>
> >>> demo(**MyMapping())
> {'a': 'A', 'b': 'B', 'c': 'C'}
>
>
> So we already support duck-typing here.
>
> We can't use the fallback iteration interface:
>
>
> >>> class MyOtherMapping:
> ...     def __iter__(self):
> ...             return zip('xyz', 'XYZ')
> ...
> >>> demo(**MyOtherMapping())
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: __main__.demo() argument after ** must be a mapping, not
> MyOtherMapping
>
>
> so that's a possible enhancement: dict unpacking should(?) fall back on
> iteration of (key, value) pairs just as dict.update does. I would
> cautiously support adding that as an enhancement.
>
>
> > What about:
> > `Iterator[Tuple[str, int]]`
>
> I said I would *cautiously* support that, because there are some subtle
> issues to do with exceptions, but we can worry about that later.
>
>
> > ```
> > @dataclass
> > class MyMap:
> >     x: int
> >     y: int
> > ```
> >
> > Is this "mapping"?
>
> No:
>
> >>> issubclass(MyMap, collections.abc.Mapping)
> False
>
> It doesn't even duck-type as a mapping. It does not support len, keys or
> subscripting:
>
>
> >>> obj = MyMap(2, 3)
> >>> len(obj)
> TypeError: object of type 'MyMap' has no len()
> >>> obj.keys()
> AttributeError: 'MyMap' object has no attribute 'keys'
> >>> obj['x']
> TypeError: 'MyMap' object is not subscriptable
>
>
> so it is certainly not a mapping.
>
>
>
> --
> Steve
> _______________________________________________
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/UYDIPMY2HXGL4OLEEFXBTZ2T4CK6TSVU/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Christopher Barker, PhD

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/F2EV7VISEQWKLNLCG4T35LD6RDNZPHRE/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to