>
> Bikesheddable, but I don't know why having these two be equivalent:
>
> @decorator var
> @decorator var = None
>
> ..would be a problem. Having an implied default of None for var above
> makes sense to my brain. Do you have an example in mind where you think it
> would create a problem?
>

I don't have anything immediately in mind, no, but I think that given the
semantics of those two statements are very different, it is at least
worthwhile to allow the decorator to know which of them is actually
happening (is `None` being assigned to the name or is it maybe just a type
hint for that name?). Keep in mind that if no assignment is happening then
there is no need to return anything from the decorator, since it will just
be lost anyway.

And I'm pretty much 100% positive that even if I can't think of a use-case
off the top of my head, there will eventually be a library author (if this
proposal is accepted) who will have some cool idea that will require
distinguishing these two scenarios. Like for example if this were used for
a CLI-building library (think something like Typer) how the assignment to
`None` could signify that it is an option with a default value of `None`,
whereas the bare name would signify that it is a mandatory argument.


Oh, and I think I've just discovered another thing that I'm not 100% sure I
like. Even putting aside that I'm not a fan of decorators on the same line
as the statement they are decorating (as I mentioned in an earlier
response), you've got examples of variable decorators where no assignment
is happening such as:

@decorator var

To me this breaks the symmetry between function decorators, which always
decorate a function definition (an implicit form of assignment), and the
proposed variable decorators.

They are also confusing in the sense that the decorator is de-facto turning
an otherwise invalid python statement legal. If you remove the decorator
from the above example you will presumably get a `NameError`.

I imagine this would then have to be special-cased somehow in the language
spec so that an undefined name is not evaluated, but only when preceded by
a decorator? I don't know, it seems messy to me.

Also, I just can't quite see the value in them if I'm honest, whereas the
version that is applied to an assignment statement:

@decorator var: bool = True

And even a bare type-hint version:

@decorator var: bool

seem to me to be far more self-evidently useful.


On Thu, May 27, 2021 at 5:45 PM Ricky Teachey <ri...@teachey.org> wrote:

> On Thu, May 27, 2021 at 11:09 AM Matt del Valle <matthew...@gmail.com>
> wrote:
>
>>
>>> I'm not the OP, but the way I understand the proposal
>> __decoration_call__ is only invoked when you actually *use an object to
>> decorate something*. That means that a decorator factory will just
>> invoke __call__ as normal, because it's nothing but a convenient way to
>> generate a decorator. It is not itself a decorator, nor is it used to
>> actually decorate anything. To illustrate this point we can separate it out
>> across several lines:
>>
>> @factory("foo")
>> def bar():
>>     pass
>>
>>
>> Can be rewritten as:
>>
>> decorator = factory("foo")
>>
>> @decorator
>> def bar():
>>     pass
>>
>>
>> So __decorator_call__ will only be invoked on the object that gets
>> returned from `factory("foo")`, not on `factory`.
>>
>
> Correct.
>
>
>> It seems to me that this proposal means that we can't even tell which of
>>> the two protocols (classic decoration, or new `__decoration_call__`
>>> style decoration) without digging into the implementation of the
>>> decorator.
>>>
>>> To be precise, the problem here as reader isn't so much the fact that I
>>> don't know whether the object is called using the `__call__` protocol or
>>> the new-style `__decorator_call__` protocol, but the fact that I can't
>>> tell whether the calls will involve the name being passed or not.
>>>
>>
>>
>> The OP mentioned a default implementation for __decoration_call__ of:
>>
>> def  __decoration_call__(self, func, by_name):
>>     if func is None:
>>         return self(by_name)
>>     return self(func)
>>
>>
>> Such that you can assume that the decorator will *always* receive the
>> name, but may choose to discard it and not make use of it if it doesn't
>> implement the __decoration_call__ interface and instead opts to use default
>> implementation which falls back on __call__.
>>
>
> Yes but I am on the fence as to whether this default implementation (I
> suppose it would live on the object class?) should be considered or not. It
> would certainly provide a lot of functionality "out-of-the-box".
>
> For decorated functions the name can always be pulled out of the function
>> object as normal even when using __call__, but to make use of the name in a
>> decorated assignment statement the decorator would have to override
>> __decoration_call__.
>>
>>
>> At this point I will say that I may be putting words into OPs mouth, and
>> would be happy to be corrected if I've misunderstood.
>>
>
> Nah you got it.
>
>
>> One final point I've just thought of is that Ricky suggested that when no
>> value is assigned to a name that the object reference be `None`. But I
>> don't think that works, because it becomes indistinguishable from when
>> `None` is explicitly assigned. We would need some sentinel value instead of
>> `None` to remove ambiguity in this situation:
>>
>>
>> from somewhere import NOTSET
>>
>>
>> @decorate
>> foo: int
>>
>> def __decoration_call__(self, obj, names, annotation):
>>     print(obj is None)    # False
>>     print(obj is NOTSET)  # True
>>
>> @decorate
>> foo: int = None
>>
>>
>> def __decoration_call__(self, obj, names, annotation):
>>     print(obj is None)    # True
>>     print(obj is NOTSET)  # False
>>
>>
>>
> Bikesheddable, but I don't know why having these two be equivalent:
>
> @decorator var
> @decorator var = None
>
> ..would be a problem. Having an implied default of None for var above
> makes sense to my brain. Do you have an example in mind where you think it
> would create a problem?
>
>
> ---
> Ricky.
>
> "I've never met a Kentucky man who wasn't either thinking about going home
> or actually going home." - Happy Chandler
>
>
_______________________________________________
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/C3KDVVT2AFC5ROUFQ7ZYNGBH2QSBKKUY/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to