On 8/11/21 2:48 AM, Jukka Lehtosalo wrote:
On Wed, Aug 11, 2021 at 10:32 AM Thomas Grainger <tagr...@gmail.com
<mailto:tagr...@gmail.com>> wrote:
Larry Hastings wrote:
> On 8/11/21 12:02 AM, Thomas Grainger wrote:
> > I think as long as there's a test case for something like
> > @dataclass
> > class Node:
> > global_node: ClassVar[Node | None]
> > left: InitVar[Node | None]
> > right: InitVar[None | None]
> >
> > the bug https://bugs.python.org/issue33453
<https://bugs.python.org/issue33453> and the current
implementation
https://github.com/python/cpython/blob/bfc2d5a5c4550ab3a2fadeb9459b4bd948ff6.
<https://github.com/python/cpython/blob/bfc2d5a5c4550ab3a2fadeb9459b4bd948ff6.>..
shows this is a tricky problem
> > The most straightforward workaround for this is to skip the
decorator
> syntax. With PEP 649 active, this code should work:
> class Node:
> global_node: ClassVar[Node | None]
> left: InitVar[Node | None]
> right: InitVar[None | None]
> Node = dataclass(Node)
> //arry/
the decorator version simply has to work
I also think that it would be unfortunate if the decorator version
wouldn't work. This is a pretty basic use case.
So, here's an idea, credit goes to Eric V. Smith. What if we tweak how
decorators work, /juuuust sliiiightly/, so that they work like the
workaround code above?
Specifically: currently, decorators are called just after the function
or class object is created, before it's bound to a variable. But we
could change it so that we first bind the variable to the initial value,
then call the decorator, then rebind. That is, this code:
@dekor8
class C:
...
would become equivalent to this code:
class C:
...
C = dekorate(C)
This seems like it would solve the class self-reference problem--the
"Node" example above--when PEP 649 is active.
This approach shouldn't break reasonable existing code. That said, this
change would be observable from Python, and pathological code could
notice and break. For example:
def ensure_Foo_is_a_class(o):
assert isinstance(Foo, type)
return o
class Foo:
...
@ensure_Foo_is_a_class
def Foo():
...
This terrible code currently would not raise an assertion. But if we
made the proposed change to the implementation of decorators, it would.
I doubt anybody does this sort of nonsense, I just wanted to fully flesh
out the topic.
If this approach seems interesting, here's one wrinkle to iron out.
When an object has multiple decorators, would we want to re-bind after
each decorator call? That is, would
@dekor1
@dekor2
@dekor3
class C:
...
turn into approach A:
class C:
...
C = dekor1(dekor2(dekor3(C)))
or approach B:
class C:
...
C = dekor3(C)
C = dekor2(C)
C = dekor1(C)
I definitely think "approach B" makes more sense.
//arry/
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-dev@python.org/message/OA4J23TU3XACE5NAUUQNQQ52BXGNHUIS/
Code of Conduct: http://python.org/psf/codeofconduct/