From: Terry Reedy on 7 Jun 2010 18:04 The answer depends on the version: in 2.5 "If the syntax "**expression" appears in the function call, "expression" must evaluate to a (subclass of) dictionary, " in 3.1 "If the syntax **expression appears in the function call, expression must evaluate to a mapping," ReferenceManual.Epressions.Primaries.Calls Terry Jan Reedy
From: Ian Kelly on 7 Jun 2010 18:32 On Mon, Jun 7, 2010 at 4:03 PM, Peter Otten <__peter__(a)web.de> wrote: > The following experiment shows that you only need to implement a keys() and > __getitem__() method. > > $ cat kw.py > class A(object): > def keys(self): return list("ab") > def __getitem__(self, key): > return 42 > > def f(**kw): > print(kw) > > f(**A()) > $ python kw.py > {'a': 42, 'b': 42} This seems to require Python 2.6. With 2.5, you get: Traceback (most recent call last): File "kw.py", line 9, in <module> f(**A()) TypeError: f() argument after ** must be a dictionary Cheers, Ian
From: Terry Reedy on 8 Jun 2010 02:18 On 6/7/2010 6:03 PM, Peter Otten wrote: > kkumer wrote: > >> >> I have to merge two dictionaries into one, and in >> a "shallow" way: changing items should be possible >> by operating either on two parents or on a >> new dictionary. I am open to suggestions how >> to do this (values are always numbers, BTW), but >> I tried to do it by creating a dict-like class that just >> forwards all calls to the two parent dicts, see below. >> >> It works, but one important thing is missing. I >> am not able to expand new dictionary with >> double-star operator ** to use it as a >> set of keyword arguments of a function. >> I googled a bit, but was unable to find what >> property must an object have to be correctly >> treated by **. > > The following experiment shows that you only need to implement a keys() and > __getitem__() method. > > $ cat kw.py > class A(object): > def keys(self): return list("ab") > def __getitem__(self, key): > return 42 > > def f(**kw): > print(kw) > > f(**A()) > $ python kw.py > {'a': 42, 'b': 42} > > However, if you have A inherit from dict... > > $ cat kwd.py > class A(dict): > def keys(self): return list("ab") > def __getitem__(self, key): > return 42 > > def f(**kw): > print(kw) > > f(**A()) > $ python kwd.py > {} > > it stops working -- probably a side-effect of some optimization. > So if you change your hubDict's base class from dict to object you should > get the desired behaviour. In 2.6, the requirement changed from '(subclass of) dictionary' to 'mapping' so this is a bit strange. It sort of looks like a bug. I will test with 3.1 tomorrow (later today, actually). tjr
From: Kresimir Kumericki on 8 Jun 2010 05:01 Peter Otten <__peter__(a)web.de> wrote: > kkumer wrote: > >> >> I have to merge two dictionaries into one, and in >> a "shallow" way: changing items should be possible >> by operating either on two parents or on a >> new dictionary. I am open to suggestions how >> to do this (values are always numbers, BTW), but >> I tried to do it by creating a dict-like class that just >> forwards all calls to the two parent dicts, see below. >> >> It works, but one important thing is missing. I >> am not able to expand new dictionary with >> double-star operator ** to use it as a >> set of keyword arguments of a function. >> I googled a bit, but was unable to find what >> property must an object have to be correctly >> treated by **. > > The following experiment shows that you only need to implement a keys() and > __getitem__() method. > > $ cat kw.py > class A(object): > def keys(self): return list("ab") > def __getitem__(self, key): > return 42 > > def f(**kw): > print(kw) > > f(**A()) > $ python kw.py > {'a': 42, 'b': 42} > > However, if you have A inherit from dict... > > $ cat kwd.py > class A(dict): > def keys(self): return list("ab") > def __getitem__(self, key): > return 42 > > def f(**kw): > print(kw) > > f(**A()) > $ python kwd.py > {} > > it stops working -- probably a side-effect of some optimization. > So if you change your hubDict's base class from dict to object you should > get the desired behaviour. > > Peter -- Kresimir Kumericki http://www.phy.hr/~kkumer/
From: Bryan on 8 Jun 2010 05:27 Terry Reedy wrote: > Peter Otten wrote: > > > kkumer wrote: > > >> I have to merge two dictionaries into one, and in > >> a "shallow" way: changing items should be possible > >> by operating either on two parents or on a > >> new dictionary. I am open to suggestions how > >> to do this (values are always numbers, BTW), but > >> I tried to do it by creating a dict-like class that just > >> forwards all calls to the two parent dicts, see below. > > >> It works, but one important thing is missing. I > >> am not able to expand new dictionary with > >> double-star operator ** to use it as a > >> set of keyword arguments of a function. > >> I googled a bit, but was unable to find what > >> property must an object have to be correctly > >> treated by **. > > > The following experiment shows that you only need to implement a keys() and > > __getitem__() method. > > > $ cat kw.py > > class A(object): > > def keys(self): return list("ab") > > def __getitem__(self, key): > > return 42 [...] > > However, if you have A inherit from dict... [...] > > it stops working -- probably a side-effect of some optimization. > > So if you change your hubDict's base class from dict to object you should > > get the desired behaviour. > > In 2.6, the requirement changed from '(subclass of) dictionary' to > 'mapping' so this is a bit strange. It sort of looks like a bug. I will > test with 3.1 tomorrow (later today, actually). I get the same bug-like behavior in 3.1. I think Peter is right that it's probably a side-effect of an optimization. kkumer seems to have completely over-ridden the methods of dict, but if we insert into his hubDict with the parent class's method: dict.__setitem__(dh, 'c', 3) Then the **dh argument passes the keyword arg c=3. -- --Bryan
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: Python + vim + spaces vs tab Next: PyCon Australia 2010 registration deadline reminder |