[Python-ideas] Python-ideas Digest, Vol 142, Issue 22
James Lu
jamtlu at gmail.com
Fri Sep 7 15:09:01 EDT 2018
What if * and ** forwarded all unnamed arguments to a function? Example:
import traceback
def print_http_response(request, color=True):
...
def print_invalid_api_response(error, *, show_traceback=False, **):
print_http_response(*, **)
if show_traceback:
traceback.print_last()
else:
print(error)
This would essentially allow * and ** to be used to call a function without having to give a name: *args or **kwargs.
However in this scenario, the client function is more likely to be “inheriting from” the behavior of the inner function, in a way where all or most of the arguments of the inner function are valid on the client function. Example: requests.get creates a Request object and immediately sends the response while blocking for it.
> On Sep 6, 2018, at 3:27 PM, python-ideas-request at python.org wrote:
>
> Send Python-ideas mailing list submissions to
> python-ideas at python.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
> https://mail.python.org/mailman/listinfo/python-ideas
> or, via email, send a message with subject or body 'help' to
> python-ideas-request at python.org
>
> You can reach the person managing the list at
> python-ideas-owner at python.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of Python-ideas digest..."
>
>
> Today's Topics:
>
> 1. Re: On evaluating features [was: Unpacking iterables for
> augmented assignment] (Franklin? Lee)
> 2. Re: On evaluating features [was: Unpacking iterables for
> augmented assignment] (Chris Angelico)
> 3. Re: Keyword only argument on function call (Jonathan Fine)
> 4. Re: On evaluating features [was: Unpacking iterables for
> augmented assignment] (Franklin? Lee)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Thu, 6 Sep 2018 14:38:26 -0400
> From: "Franklin? Lee" <leewangzhong+python at gmail.com>
> To: Chris Angelico <rosuav at gmail.com>
> Cc: Python-Ideas <python-ideas at python.org>
> Subject: Re: [Python-ideas] On evaluating features [was: Unpacking
> iterables for augmented assignment]
> Message-ID:
> <CAB_e7iyjcFLCCmnbviUDKZY6mXdv0Hs7-_4kUQEpZe8mVTzvbg at mail.gmail.com>
> Content-Type: text/plain; charset="UTF-8"
>
>> On Thu, Sep 6, 2018 at 2:23 PM Chris Angelico <rosuav at gmail.com> wrote:
>>
>> On Fri, Sep 7, 2018 at 4:11 AM, Franklin? Lee
>> <leewangzhong+python at gmail.com> wrote:
>>>> On Tue, Aug 28, 2018 at 6:37 PM Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
>>>>
>>>> Guido van Rossum wrote:
>>>>> we might propose (as the OP did) that this:
>>>>>
>>>>> a, b, c += x, y, z
>>>>>
>>>>> could be made equivalent to this:
>>>>>
>>>>> a += x
>>>>> b += y
>>>>> c += z
>>>>
>>>> But not without violating the principle that
>>>>
>>>> lhs += rhs
>>>>
>>>> is equivalent to
>>>>
>>>> lhs = lhs.__iadd__(lhs)
>>>
>>> (Corrected: lhs = lhs.__iadd__(rhs))
>>>
>>> Since lhs here is neither a list nor a tuple, how is it violated? Or
>>> rather, how is it any more of a special case than in this syntax:
>>>
>>> # Neither name-binding or setitem/setattr.
>>> [a,b,c] = items
>>>
>>> If lhs is a Numpy array, then:
>>> a_b_c += x, y, z
>>> is equivalent to:
>>> a_b_c = a_b_c.__iadd__((x,y,z))
>>>
>>> We can translate the original example:
>>> a, b, c += x, y, z
>>> to:
>>> a, b, c = target_list(a,b,c).__iadd__((x,y,z))
>>> where `target_list` is a virtual (not as in "virtual function") type
>>> for target list constructs.
>>
>> What is the virtual type here, and what does its __iadd__ method do? I
>> don't understand you here. Can you go into detail? Suppose I'm the
>> author of the class that all six of these objects are instances of;
>> can I customize the effect of __iadd__ here in some way, and if so,
>> how?
>
> I shouldn't have used jargon I had to look up myself.
>
> The following are equivalent and compile down to the same code:
> a, b, c = lst
> [a, b, c] = lst
>
> The left hand side is not an actual list (even though it looks like
> one). The brackets are optional. The docs call the left hand side a
> target list: https://docs.python.org/3/reference/simple_stmts.html#assignment-statements
>
> "Target list" is not a real type. You can't construct such an object,
> or hold one in memory. You can't make a class that emulates it
> (without interpreter-specific hacks), because it is a collection of
> its names, not a collection of values.
>
> target_list.__iadd__ also does not exist, because target_list does not
> exist. However, target_list can be thought of as a virtual type, a
> type that the compiler compiles away. We can then consider
> target_list.__iadd__ as a virtual operator, which the compiler will
> understand but hide from the runtime.
>
> I was making the point that, because the __iadd__ in the example does
> not refer to list.__iadd__, but rather a virtual target_list.__iadd__,
> there is not yet a violation of the rule.
>
>
> ------------------------------
>
> Message: 2
> Date: Fri, 7 Sep 2018 04:46:36 +1000
> From: Chris Angelico <rosuav at gmail.com>
> To: Python-Ideas <python-ideas at python.org>
> Subject: Re: [Python-ideas] On evaluating features [was: Unpacking
> iterables for augmented assignment]
> Message-ID:
> <CAPTjJmrauU+GD+Utcm=zUGFqWX5QXOhWLg5PL94s5OH_O8jLrQ at mail.gmail.com>
> Content-Type: text/plain; charset="UTF-8"
>
> On Fri, Sep 7, 2018 at 4:38 AM, Franklin? Lee
> <leewangzhong+python at gmail.com> wrote:
>> The following are equivalent and compile down to the same code:
>> a, b, c = lst
>> [a, b, c] = lst
>>
>> The left hand side is not an actual list (even though it looks like
>> one). The brackets are optional. The docs call the left hand side a
>> target list: https://docs.python.org/3/reference/simple_stmts.html#assignment-statements
>>
>> "Target list" is not a real type. You can't construct such an object,
>> or hold one in memory. You can't make a class that emulates it
>> (without interpreter-specific hacks), because it is a collection of
>> its names, not a collection of values.
>
> A target list is a syntactic element, like a name, or an operator, or
> a "yield" statement. You can't construct one, because it isn't an
> object type. It's not a "virtual type". It's a completely different
> sort of thing.
>
>> target_list.__iadd__ also does not exist, because target_list does not
>> exist. However, target_list can be thought of as a virtual type, a
>> type that the compiler compiles away. We can then consider
>> target_list.__iadd__ as a virtual operator, which the compiler will
>> understand but hide from the runtime.
>>
>> I was making the point that, because the __iadd__ in the example does
>> not refer to list.__iadd__, but rather a virtual target_list.__iadd__,
>> there is not yet a violation of the rule.
>
> What you're suggesting is on par with trying to say that:
>
> for += 5
>
> should be implemented as:
>
> current_loop.__iadd__(5)
>
> where "current_loop" doesn't really exist, but it's a virtual type
> that represents a 'for' loop. That doesn't make sense, because there
> is no object in Python to represent the loop. There is no class/type
> that represents all loops, on which a method like this could be added.
> The word 'for' is part of the grammar, not the object model. And
> "target list" is the same. There's no way to attach an __iadd__ method
> to something that doesn't exist.
>
> So for your proposal to work, you would need to break that rule, and
> give a *different* meaning to this.
>
> ChrisA
>
>
> ------------------------------
>
> Message: 3
> Date: Thu, 6 Sep 2018 20:10:49 +0100
> From: Jonathan Fine <jfine2358 at gmail.com>
> To: Anders Hovm?ller <boxed at killingar.net>
> Cc: python-ideas <python-ideas at python.org>
> Subject: Re: [Python-ideas] Keyword only argument on function call
> Message-ID:
> <CALD=Yf8Ddn4MQnbLw+ouoac7YQedc_EsK8o5PyKuwetMuNMAbg at mail.gmail.com>
> Content-Type: text/plain; charset="UTF-8"
>
> Summary: I addressed the DEFINING problem. My mistake. Some rough
> ideas for the CALLING problem.
>
> Anders has kindly pointed out to me, off-list, that I solved the wrong
> problem. His problem is CALLING the function fn, not DEFINING fn.
> Thank you very much for this, Anders.
>
> For calling, we can use https://docs.python.org/3/library/functions.html#locals
>
>>>> lcls = locals()
>
>>>> a = 'apple'
>>>> b = 'banana'
>>>> c = 'cherry'
>
>>>> dict((k, lcls[k]) for k in ('a', 'b', 'c'))
> {'b': 'banana', 'c': 'cherry', 'a': 'apple'}
>
> So in his example
>
> foo(a=a, b=b, c=c, d=3, e=e)
>
> one could instead write
>
> foo(d=3, **helper(locals(), ('a', 'b', 'c', 'e')))
>
> or perhaps better
>
> helper(locals(), 'a', 'b', 'c', 'e')(foo, d=3)
>
> where the helper() picks out items from the locals(). And in the
> second form, does the right thing with them.
>
> Finally, one might be able to use
>
>>>> def fn(*, a, b, c, d, e): f, g, h = 3, 4, 5
>>>> fn.__code__.co_kwonlyargcount
> 5
>>>> fn.__code__.co_varnames
> ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h')
>>>> fn.__code__.co_argcount
> 0
>
> to identify the names of all keyword arguments of the function foo(),
> and they provide the values in locals() as the defaults. Of course,
> this is somewhat magical, and requires strict conformance to
> conventions. So might not be a good idea.
>
> The syntax could then be
>
> localmagic(foo, locals())(d=3)
>
> which, for magicians, might be easier. But rightly in my opinion,
> Python is reluctant to use magic.
>
> On the other hand, for a strictly controlled Domain Specific Language,
> it might, just might, be useful. And this list is for "speculative
> language ideas" (see
> https://mail.python.org/mailman/listinfo/python-ideas).
>
> --
> Jonathan
>
>
> ------------------------------
>
> Message: 4
> Date: Thu, 6 Sep 2018 15:26:47 -0400
> From: "Franklin? Lee" <leewangzhong+python at gmail.com>
> To: Chris Angelico <rosuav at gmail.com>
> Cc: Python-Ideas <python-ideas at python.org>
> Subject: Re: [Python-ideas] On evaluating features [was: Unpacking
> iterables for augmented assignment]
> Message-ID:
> <CAB_e7iyiM2ByZKxToNumtVRMTZr0S0K8-zyBykUbKYvv7AeQKQ at mail.gmail.com>
> Content-Type: text/plain; charset="UTF-8"
>
> n Thu, Sep 6, 2018 at 2:47 PM Chris Angelico <rosuav at gmail.com> wrote:
>>
>> On Fri, Sep 7, 2018 at 4:38 AM, Franklin? Lee
>> <leewangzhong+python at gmail.com> wrote:
>>> The following are equivalent and compile down to the same code:
>>> a, b, c = lst
>>> [a, b, c] = lst
>>>
>>> The left hand side is not an actual list (even though it looks like
>>> one). The brackets are optional. The docs call the left hand side a
>>> target list: https://docs.python.org/3/reference/simple_stmts.html#assignment-statements
>>>
>>> "Target list" is not a real type. You can't construct such an object,
>>> or hold one in memory. You can't make a class that emulates it
>>> (without interpreter-specific hacks), because it is a collection of
>>> its names, not a collection of values.
>>
>> A target list is a syntactic element, like a name, or an operator, or
>> a "yield" statement. You can't construct one, because it isn't an
>> object type. It's not a "virtual type". It's a completely different
>> sort of thing.
>
> I didn't think I gave the impression that I was complaining about not
> being able to construct it. I gave an explanation for how it isn't a
> real type, because you asked how you could modify the behavior, and
> because I wanted to give an explanation for more than just you.
>
> There are constructs that correspond to types (such as slices and
> functions). There are those that don't. We call `3:2` (in the right
> context) a slice, even though it's technically a construct which is
> compiled down to a `slice` object. I see no problem there.
>
> I called it a "virtual type" and explained why I called it that. You
> reject the use of that term, but you don't even acknowledge that I
> gave reasons for it.
>
>>> target_list.__iadd__ also does not exist, because target_list does not
>>> exist. However, target_list can be thought of as a virtual type, a
>>> type that the compiler compiles away. We can then consider
>>> target_list.__iadd__ as a virtual operator, which the compiler will
>>> understand but hide from the runtime.
>>>
>>> I was making the point that, because the __iadd__ in the example does
>>> not refer to list.__iadd__, but rather a virtual target_list.__iadd__,
>>> there is not yet a violation of the rule.
>>
>> What you're suggesting is on par with trying to say that:
>>
>> for += 5
>>
>> should be implemented as:
>>
>> current_loop.__iadd__(5)
>>
>> where "current_loop" doesn't really exist, but it's a virtual type
>> that represents a 'for' loop.
>
> I explained how target_list could be thought of as a special imaginary
> type which only exists in the compiler's "mind", and then extended
> that to an imaginary method on that type. Of course your example shows
> absurdity: you didn't try to say how a for-loop is like an object in
> the first place.
>
>> That doesn't make sense, because there
>> is no object in Python to represent the loop. There is no class/type
>> that represents all loops, on which a method like this could be added.
>> The word 'for' is part of the grammar, not the object model. And
>> "target list" is the same. There's no way to attach an __iadd__ method
>> to something that doesn't exist.
>
> But I'm not using the word `for`. I am using constructs like `[a,b,c]`
> (where it is not a list). At least use `(for x in y: z) += 5` as your
> example. You're effectively accusing me of trying to make `[` (a
> single token, not a full construct) an object.
>
> Your argument here is that there is no Python object to represent a
> loop, but that really means there's no _runtime_ object to represent a
> loop. I already said that target lists don't exist in memory (i.e.
> runtime).
>
> "Target list" does exist, just not as a runtime type. It exists as an
> abstraction not available to the runtime, and we can extend that
> abstraction in ways not available to the runtime. That means that you
> can't attach it during the runtime. It does not mean you can't reason
> with it during compile-time.
>
>> So for your proposal to work, you would need to break that rule, and
>> give a *different* meaning to this.
>
> It is not my proposal. I was questioning how there was a rule
> violation about x+=y translating to `x = x.__iadd__(y)`. You're
> talking about a different, made-up rule about how syntactical
> constructs can't correspond to compile-time imaginary objects or
> runtime objects. But there are syntactical constructs that DO
> correspond to runtime types (slice, list, class), there are those
> which don't but can (let's not get into that), there are those which
> can stay compile-time (f-strings, target lists), and there are those
> which probably can't be thought of as types at all (import).
>
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
>
>
> ------------------------------
>
> End of Python-ideas Digest, Vol 142, Issue 22
> *********************************************
More information about the Python-ideas
mailing list