On Mon, Dec 28, 2020 at 12:33 PM Guido van Rossum <gu...@python.org> wrote:

> On Mon, Dec 28, 2020 at 12:15 PM Christopher Barker <python...@gmail.com>
> wrote:
>
>> 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.
>>
>
> There may be a (small) performance issue with that -- items() requires
> creating a tuple object for each key/value pair.
>

it does look like items() is a tad faster (dict with 1000 items), but not
enough to matter:

In [61]: %timeit {k: d[k] for k in d.keys()}
112 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [62]: %timeit {k: v for k, v in d.items()}
92.6 µs ± 1.9 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Anyway, of course it's too late to change. And there are probably other
> "protocols" that check for the presence of keys and __getitem__(). Also, in
> a sense keys() is more fundamental -- deriving keys() from items() would be
> backwards (throwing away the values -- imagine a data type that stores the
> values on disk).
>

Does there need to be a single defined "protocol" for a mapping (other than
the ABC)? -- that is, would **unpacking be able to use .items() and keys()
be used in other contexts?

And why does ** unpacking need to check at all (LBYL) couldn't it simply do
something like:

{k: d[k] for k in d}

sure, there could occasionally be a Sequence for which that would happen to
work (like a range object for instance), but then it would be unlikely to
result in the expected result anyway -- just like many other uses of Duck
typing. Or not, and it could still be correct.

But as you say -- too late the change now anyway.

To the OP: you suggested that you had, I think, four ways to make a
dataclass "unpackable", but none were satisfactory. How about this
decorator:

def make_mapping(cls):
    def __getitem__(self, key):
        if key in self.__dataclass_fields__:
            return self.__dict__[key]
        else:
            raise KeyError(key)

    def keys(self):
        return self.__dataclass_fields__.keys()

    cls.__getitem__ = __getitem__
    cls.keys = keys

    return cls

@make_mapping
@dataclasses.dataclass
class Point:
    x: int
    y: int

p = Point(1, 2)

print(p)

print({**p})
print(dict(p))

-CHB

Side Question: when should one use __dict__ vs vars() vs getattr() ??? all
three work in this case, but I'm never quite sure which is prefered, and
why.








>
>
>> 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.
>>
>
> If we had to do it all over from scratch we would probably design mappings
> and sequences to be differentiably using dunders only. But it's about 31
> years too late for that. And looking at the mess JavaScript made of this
> (sequences are mappings with string keys "0", "1" and so on), I'm pretty
> happy with how Python did this.
>
> --
> --Guido van Rossum (python.org/~guido)
> *Pronouns: he/him **(why is my pronoun here?)*
> <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
>


-- 
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/ZPDXCZSYVPXMV54T54BUH233SYYFQ7FA/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to