[Python-ideas] Short form for keyword arguments and dicts
Joshua Landau
joshua.landau.ws at gmail.com
Wed Jun 26 16:46:26 CEST 2013
On 26 June 2013 09:04, Ethan Furman <ethan at stoneleaf.us> wrote:
> On 06/26/2013 12:48 AM, Greg Ewing wrote:
>>
>> Ron Adam wrote:
>>>
>>> And I don't like the '=' with nothing on the right.
>>
>>
>> Expanding on the suggestion someone made of having a
>> single marker of some kind in the argument list, I
>> came up with this:
>>
>> def __init__(self, text, font = system_font, style = 'plain'):
>> default_size = calc_button_size(text, font, style)
>> Widget.__init__(self, size = default_size, pass font, style)
>
>
> I don't care for it.
>
> A word doesn't stand out like a character does, plus this usage of pass is
> completely different from its normal usage.
>
> We're already used to interpreting '*' as a coin with two sides, let's stick
> with it:
>
> def apply_map(map, target, *, frobble): # '*' means frobble is keyword
> only
> ...
>
> and later:
>
> frobble = some_funny_stuff_here()
> .
> .
> .
> apply_map(map=kansas, target=toto, *, frobble) # '*' means frobble maps
> to keyword frobble
Whilst Greg Ewing has made me also much more sympathetic to this view,
I feel that:
1) This is nearly unreadable - it does not say what it does in the slightest
2) It's added syntax - that's a high barrier. I'm not convinced it's
worth it yet.
3) It still feels like hackery; I might prefer something explicitly
hackery like this:
apply_map(map=kansas, target=toto, **locals("frobble"))
where locals is:
def locals(*args):
if args:
return {arg:original_locals()[arg] for arg in args}
else:
return original_locals()
For Greg's he'd use:
def __init__(self, text="Hello", font=system_font, **kwds):
default_size = calc_default_size(text, font)
Widget.__init__(self, size=default_size, **locals("font"), **kwds)
or even
def __init__(self, text = "Hello", font = system_font, **kwds):
default_size = calc_default_size(text, font)
Widget.__init__(self, **locals("size", "font"), **kwds)
under the asumption that http://bugs.python.org/issue2292 does get
implemented first.
For reference, he is using (respaced for consistency):
def __init__(self, text="Hello", font=system_font, **kwds):
default_size = calc_default_size(text, font)
Widget.__init__(self, size=default_size, font=font, **kwds)
Note that this is only a way to suggest that *there might be another
way*; maybe something involving objects.
3 cont.) The reason I think it feels like hackery is simply that I
don't feel like Python is ever "reference by name"; objects don't know
what they are called (some know what they *were* named; but they have
no guarantee it's true) it feels *very wrong* to give "foobar" to
function and have that function somehow extract the name! I know it's
not doing that, but it's ever-so-close.
However; maybe:
class AttrDict(dict):
def __init__(self, mapping, **defaults):
super().__init__(defaults, **mapping)
self.__dict__ = self
def __init__(self, **kwds):
kwds = AttrDict(kwds, text="Hello", font=system_font)
kwds.size = calc_default_size(kwds.text, kwds,font)
Widget.__init__(self, **kwds)
and a decorator could even make this:
@dynamic_kwds(text="Hello", font=system_font)
def __init__(self, kwds):
kwds.size = calc_default_size(kwds.text, kwds,font)
Widget.__init__(self, **kwds)
which would have the same run-time effect as the original (the second
keeps re-evaluating the signature).
Again; I mention these only to show people not to have a restricted
idea on what the solution looks like - don't just try and fix the
symptoms of the problem.
More information about the Python-ideas
mailing list