
I am confused why you are okay with @decorator var: bool
but not
@decorator var
Yes, a bare name is currently an error while just a name and a type hint is valid, but the latter doesn't bind anything to the name, and using that identifier is still a NameError. So a decorator presumably can't return a value for either (or it could, but it would always be dropped). What could it do with a name and a type hint that is so much better than just a name?
To reiterate my point from earlier in the thread, I am quite firmly opposed to having the decorator on the same line as the statement being decorated. I'll just copy-paste my reasoning for it: I like this:
@typing.TypeVar T = str, bytes
about a million times better than:
@typing.TypeVar T = str, bytes
Because the latter feels (to me) too similar for comfort to this:
int foo = 3
Which is in my mind not very pythonic. Also, my brain just has an easier time parsing the multiline version than the single-line one (though I concede that a combination of familiarity and syntax highlighting would solve that issue eventually).
It also represents an asymmetry between the syntax of the proposed assignment decorators and the syntax for function and class decorators.
And finally, it doesn't cleanly accommodate use-cases like those proposed by Stéfane in the previous thread:
@acl(READ, WRITE) @constraint(10 < _ < 100) @not_null @indexed @depends_on(whatever) @inject first_name: str
Whereas the multiline variant does.
And regarding your proposal to relax the newline requirement on function/class decorators: I got the sense that people both liked reading my examples of same-line
decorators and pushed back against not making them appear just like function decorators. One way to have my cake and you eat it too would be to relax the current decorator grammar to not require a NEWLINE. AFAICT there would be no ambiguity since after a decorator there must either be another "@" or a "def". Then both function and assignment decorating can be both. These would all be possible and not change the status quo.
@cache def factorial(n): pass
This would admittedly resolve the asymmetry between the proposed single-line variable decorator syntax and current decorators, but personally I just *really* don't like it. The only benefit is saving a line, but it comes at (in my opinion, your mileage may vary) a huge cost to legibility, and it goes against the zen: There should be one-- and preferably only one --obvious way to do it. And it's just something that has (almost) no precedent in python (aside from `async def`). It has the feel of something like: public static final native abstract void SomeMethod() {...} I'm imagining a future of reading python code like: @too @many("!") @decorators @on("a", "single", "line") def foo(...): And it makes me unhappy :( So going back to your original point of why I'm okay with decorating a bare type-hint, like: @decorate foo: int But not @decorate foo The reason is simply that if you take the decorator away the first one is legal, and the second one will raise `NameError`. I'm happy to decorate a statement that is valid on its own, but I'm against the idea of special-casing decorator syntax so that it can decorate otherwise-invalid statements. And I do think that there are legitimate uses for decorating a bare type-hint, since it does actually contain useful information the decorator might want to capture (for example, in one of its own instance attributes if the decorator is an object rather than a function, which it would have to be in order to implement __decoration_call__). You're right in that it wouldn't be able to return anything since no assignment is taking place, but there are still potential use-cases for it. I'll concede that there are also use-cases for decorating a completely naked name, but none of the ones I've seen so far seem to me compelling enough to break the rules like this. On Thu, May 27, 2021 at 8:43 PM Ricky Teachey <ricky@teachey.org> wrote:
Whoops, replying all this time.
On Thu, May 27, 2021 at 2:32 PM micro codery <ucodery@gmail.com> wrote:
On Thu, May 27, 2021 at 10:40 AM Matt del Valle <matthewgdv@gmail.com> wrote:
I am still very confused as to the scope of this counter proposal re variable decorating. I have only seen two such examples here
@decorator variable # variable = decorator.__decoration_call__(None, "variable")
@decorator variable = "spam" # variable = decorator.__decoration_call__(variable, "variable")
But what is actually valid to follow a decorator in this proposal? Any simple expression, any expression? Is it limited to assignment espressions?
At this point, I have in mind any expression that appears to the right, which I believe is what is allowed today:
@1/2 "lala" and money def func(): ...
Here are some interesting uses that were brought up in the other thread and I would like to know how they would work.
@decorator spam = eggs = cheese = "tomatoes"
@decorator spam, eggs, cheese = "tomatoes"
@decorator spam, eggs = cheese = "tomatoes"
@decorator spam = (eggs := "cheese)
@decorator locals()[find_it() or "default"] = spam()
Regards, ~Jeremiah
I would also like to know how all of these work :D I am not sure about most of them but open to suggestions.
The only one that I feel confident about is:
@decorator spam = (eggs := "cheese)
...which, I think, should be:
decorator.__decoration_call__(spam, "spam")
Unfortunately for the proposal most people don't seem too thrilled with it. So I don't plan to spend a lot of time thinking through these examples and suggesting behavior. Anyone is welcome to do that though, this isn't MINE in the sense I am jealously guarding ownership of the details. :)
On Thu, May 27, 2021 at 3:03 PM Brendan Barnwell <brenbarn@brenbarn.net> wrote:
On 2021-05-26 09:43, Ricky Teachey wrote:
These two ideas of a decorator syntax result are not the same:
RESULT A: function decorator # func = decorator("spam")(func)
RESULT B: variable decorator # name = decorator("spam")("name")
...because func is passed as an object, but "name" a string representing the name of the object. Two very different things.
For this reason I think I would agree even more so that the differences in the decorator behavior would be an extremely significant point of confusion.
This got me to thinking: what if access to the variable name were provided by another means, and ONLY when the decorator syntax is employed?
This seems contradictory to me. It looks like you're saying, "We shouldn't use decorator syntax to represent two different things (object vs name), but instead decorator syntax should give us access to two different things (object vs name)." I realize based on your proposal there is a distinction here but I think it's quite a narrow one and doesn't resolve the basic problem, which is that currently decorators operate on objects and these new proposals are about making them operate on names.
I think there may be value in having some feature that lets us get access to the name side of an assignment. But I wouldn't call such a thing a "decorator", nor would I want to use the same @ syntax that is used for decorators. To me that would be confusing, because the behavior is totally different. Even with your __decorator_call__ proposal, there's still a jarring shift from, in some cases, using just the object, and in other cases stuffing a new parameter (the name) into the parameter list. That seems awkward to me.
-- Brendan Barnwell
Yes, and for this reason I really liked Steve's googly eyes proposal in the other thread. But I wonder if there value in specifically giving decorators access to the name side?
It seems to me that it would open up a lot of possibilities, just as when descriptors learned their names.
class Desc: def __set_name__(self, owner, name): self.name = name def __get__(self, instance, owner): if instance is None: pass print(f"I am { owner.__name__}.{self.name}")
class C: v = Desc()
C().v I am C.v
We could make the __decoration_call__ method even more powerful. We could give it access not just to the name side, but to the type info, and even the code object/expression side (i.e., RHS).
@decorator x: Fraction = 1/2 # decorator.__decoration_call__(x, "x", "1/2", Fraction)
So, for example, a Math library can create the feature:
@Math x: Fraction = 1/2
And x is:
Fraction(1, 2)
Yes, you can do:
x = Fraction("1/2")
...today. I get that. But it's not as if this Math example is the ONLY thing it allows you to do. You also can easily avoid repeating things and making mistakes:
@namedtuple_factory Point = "x y"
I'm sure there are many other things I haven't thought of.
--- Ricky.
"I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler
On Thu, May 27, 2021 at 3:03 PM Brendan Barnwell <brenbarn@brenbarn.net> wrote:
On 2021-05-26 09:43, Ricky Teachey wrote:
These two ideas of a decorator syntax result are not the same:
RESULT A: function decorator # func = decorator("spam")(func)
RESULT B: variable decorator # name = decorator("spam")("name")
...because func is passed as an object, but "name" a string representing the name of the object. Two very different things.
For this reason I think I would agree even more so that the differences in the decorator behavior would be an extremely significant point of confusion.
This got me to thinking: what if access to the variable name were provided by another means, and ONLY when the decorator syntax is employed?
This seems contradictory to me. It looks like you're saying, "We shouldn't use decorator syntax to represent two different things (object vs name), but instead decorator syntax should give us access to two different things (object vs name)." I realize based on your proposal there is a distinction here but I think it's quite a narrow one and doesn't resolve the basic problem, which is that currently decorators operate on objects and these new proposals are about making them operate on names.
I think there may be value in having some feature that lets us get access to the name side of an assignment. But I wouldn't call such a thing a "decorator", nor would I want to use the same @ syntax that is used for decorators. To me that would be confusing, because the behavior is totally different. Even with your __decorator_call__ proposal, there's still a jarring shift from, in some cases, using just the object, and in other cases stuffing a new parameter (the name) into the parameter list. That seems awkward to me.
-- Brendan Barnwell "Do not follow where the path may lead. Go, instead, where there is no path, and leave a trail." --author unknown _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/JNJNBY... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/EUUQXV... Code of Conduct: http://python.org/psf/codeofconduct/