osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Syntax for one-line "nonymous" functions in "declaration style"


On Tue, Apr 2, 2019 at 1:43 AM Alexey Muranov <alexey.muranov at gmail.com>
wrote:
>
> > On Mon, Apr 1, 2019 at 3:52 PM Alexey Muranov <alexey.muranov at
> > gmail.com>
> > wrote:
> > >
> > > I only see a superficial analogy with `super()`, but perhaps it is
> > > because you did not give much details of you suggestion.
> >
> > No, it's because the analogy was not meant to be anything more than
> > superficial. Both are constructs of syntactic magic that aid
> > readability at
> > a high level but potentially obscure the details of execution (in
> > relatively unimportant ways) when examined at a low level.
>
> Since i understand that the "super() magic" is just evaluation in a
> predefined environment, it does not look so very magic.

It's the reason why this doesn't work:

superduper = super

class A:
    def f(self):
        return 42

class B(A):
    def f(self):
        return superduper().f()

>>> B().f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in f
RuntimeError: super(): __class__ cell not found

But this does:

class C(A):
    def f(self):
        return superduper().f()
        not super

>>> C().f()
42

I don't know, seems magical to me.

> Moreover, without this "magic", `super()` would have just produced an
> error.  So this magic did not change behaviour of something that worked
> before, it made "magically" work something that did not work before
> (but i am still not excited about it).

I'm curious how you feel about this example then (from the CPython 3.7.2
REPL; results from different Python implementations or from scripts that
comprise a single compilation unit may vary)?

>>> 372 is 372
True
>>> b = 372; b is 372
True
>>> b = 372
>>> b is 372
False

> > Maybe it was from my talk of implementing this by replacing the
> > assignment
> > with an equivalent def statement in the AST. Bear in mind that the def
> > statement is already just a particular kind of assignment: it creates
> > a
> > function and assigns it to a name. The only difference between the
> > original
> > assignment and the def statement that replaces it is in the __name__
> > attribute of the function object that gets created. The proposal just
> > makes
> > the direct lambda assignment and the def "assignment" to be fully
> > equivalent.
>
> `def` is not an assignment, it is more than that.

def is an assignment where the target is constrained to a single variable
and the expression is constrained to a newly created function object
(optionally "decorated" first with one or more composed function calls).
The only ways in which:

@decorate
def foo(blah):
    return stuff

is more than:

foo = decorate(lambda blah: stuff)

are: 1) the former syntactically allows statements inside the function
body, not just expressions; 2) the former syntactically allows annotations
on the function; and 3) the former syntactically sets a function name and
the latter doesn't. In other words, all of the differences ultimately boil
down to syntax.