On 26 June 2013 09:04, Ethan Furman <ethan@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.