Hi all,
I'm not sure whether this idea has been discussed before or not, so I apologize in advanced if that's the case.
Consider the behavior:
f = lambda: True
f.__name__ '<lambda>' x = f x.__name__ '<lambda>'
I'm arguing the behavior above is too brittle/limited and,
considering that
the name of the attribute is __name__
, not entirely consistent with
Python's AST. Consider:
f = lambda: True
x = f
At the first line, an ast.Assign would be created whose target
is an
ast.Name whose id
is f
.
At the second line, an ast.Assign would be created whose target is an
ast.Name whose id
is x
.
However, as you can see __name__
special method returns 'lambda' in both
cases (just like it was defined
https://docs.python.org/3/library/stdtypes.html#definition.__name__),
whereas I think either it should have returned '<lambda>' and 'x' or a new
function/attribute should exist that does so and more.
For example, consider:
x_1 = 1
x_2 = 1 x_3 = 1 x_4 = x_1 for i in [x_1, x_2, x_3, x_4]: print(i) 1 1 1 1
Now assume such a function exist and is called
name
. Then:
name(1) '1'
name("Something") "Something" name(x_1) 'x_1' name(x_4) 'x_4' name(x_5) 'x_5' # Or an Exception! def itername(collection): for i in map(lambda x: name(x), collection): yield i
for i in [x_1, x_2, x_3, x_4]: print(i, name(i)) 1, 'i' 1, 'i' 1, 'i' 1, 'i' for i in itername([x_1, x_2, x_3, x_4]): print(i) 'x_1' 'x_2' 'x_3' 'x_4'
I think above example gives an idea of the behavior I'm
proposing. I can
implement it in a hacky way by parsing the block into ast and going through
all the nodes that have an id
or a name
or asname
etc, but this
behavior wouldn't be pretty for run-time cases e.g. itername
in the
example above.
Anyway I'd appreciate any input.
P.S. I must confess that I can't think of a single case where having this
function is the only way to do the job, if the job is sufficiently
different from the specification of said function. It'd be only for the
sake of convenience, and continuation of what already was there with
__name__
.
On Mon, Jun 19, 2017 at 7:38 AM, Alireza Rafiei
alireza.rafiei94@gmail.com wrote:
I'm not sure whether this idea has been discussed before or not, so I apologize in advanced if that's the case.
Consider the behavior:
f = lambda: True f.__name__ '<lambda>' x = f x.__name__ '<lambda>'
I'm arguing the behavior above is too brittle/limited and,
considering that
the name of the attribute is __name__
, not entirely consistent with
Python's AST. Consider:
f = lambda: True x = f
At the first line, an ast.Assign would be created whose target
is an
ast.Name whose id
is f
.
At the second line, an ast.Assign would be created whose target is an
ast.Name whose id
is x
.
The __name__ of a function has nothing to do with an Assign node, which is simply assigning a value to something. For instance, if you do:
f = "hello"
you wouldn't expect the string "hello" to have a __name__ - it's just a string. And a lambda function normally won't be assigned to anything. You use lambda when there isn't any name:
do_stuff(lambda q: q * 2 + 1)
and you use def when you want to assign it to a name:
def f(): return True
By the time the Assign operation gets performed, the function object - with all of its attributes, including __name__ - has been completely created. I'm not sure what your proposal would do to these kinds of situations, but it shouldn't be modifying the assigned object.
ChrisA
The __name__ of a function has nothing to do with an Assign node,
which is simply assigning a value to something. For instance, if you do:
f = "hello" you wouldn't expect the string "hello" to have a __name__ - it's just a string. And a lambda function normally won't be assigned to anything. You use lambda when there isn't any name: do_stuff(lambda q: q * 2 + 1) and you use def when you want to assign it to a name: def f(): return True By the time the Assign operation gets performed, the function object - with all of its attributes, including __name__ - has been completely created. I'm not sure what your proposal would do to these kinds of situations, but it shouldn't be modifying the assigned object.
I guess I should have framed it as a quote
for
python. You're absolutely
right that it shouldn't be modifying the assigned object and it doesn't. I
mentioned the Assign to say that in x = f
, x
has name as well,
however
x.__name__
returns the name of f
and not x
.
As for the f = "hello"
, the value of the name "f" would be "hello" and
the value of the name "hello" would be "hello".
My proposal is to either change the behavior of __name__
or have
something similar that acts globally for all objects and types to get a
quote-like behavior, provided that the operands of quotes are atomic.
On Sun, Jun 18, 2017 at 2:46 PM, Chris Angelico rosuav@gmail.com wrote:
On Mon, Jun 19, 2017 at 7:38 AM, Alireza Rafiei
alireza.rafiei94@gmail.com wrote:
I'm not sure whether this idea has been discussed before or not, so I apologize in advanced if that's the case.
Consider the behavior:
f = lambda: True f.__name__ '<lambda>' x = f x.__name__ '<lambda>'
I'm arguing the behavior above is too brittle/limited and,
considering
that
the name of the attribute is __name__
, not entirely consistent with
Python's AST. Consider:
f = lambda: True x = f
At the first line, an ast.Assign would be created whose target
is an
ast.Name whose id
is f
.
At the second line, an ast.Assign would be created whose target is an
ast.Name whose id
is x
.
The __name__ of a function has nothing to do with an Assign node, which is simply assigning a value to something. For instance, if you do:
f = "hello"
you wouldn't expect the string "hello" to have a __name__ - it's just a string. And a lambda function normally won't be assigned to anything. You use lambda when there isn't any name:
do_stuff(lambda q: q * 2 + 1)
and you use def when you want to assign it to a name:
def f(): return True
By the time the Assign operation gets performed, the function object - with all of its attributes, including __name__ - has been completely created. I'm not sure what your proposal would do to these kinds of situations, but it shouldn't be modifying the assigned object.
ChrisA
Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
On Mon, Jun 19, 2017 at 8:16 AM, Alireza Rafiei
alireza.rafiei94@gmail.com wrote:
I guess I should have framed it as a
quote
for python. You're absolutely
right that it shouldn't be modifying the assigned object and it doesn't. I
mentioned the Assign to say that in x = f
, x
has name as well,
however
x.__name__
returns the name of f
and not x
.
As for the f = "hello"
, the value of the name "f" would be "hello" and
the
value of the name "hello" would be "hello".
My proposal is to either change the behavior of __name__
or have
something
similar that acts globally for all objects and types to get a quote-like
behavior, provided that the operands of quotes are atomic.
Hmm. So... after x = f, f.__name__ would be different from x.__name__?
ChrisA
On 2017-06-18 22:38, Alireza Rafiei wrote:
Hi all,
I'm not sure whether this idea has been discussed before or not, so I apologize in advanced if that's the case.
Consider the behavior:
>>> f = lambda: True
>>> f.__name__
'<lambda>'
>>> x = f
>>> x.__name__
'<lambda>'
I'm arguing the behavior above is too brittle/limited and, considering
that the name of the attribute is __name__
, not entirely consistent
with Python's AST. Consider:
>>> f = lambda: True
>>> x = f
At the first line, an ast.Assign would be created whose target is an
ast.Name whose id
is f
.
At the second line, an ast.Assign would be created whose target is an
ast.Name whose id
is x
.
However, as you can see __name__
special method returns 'lambda' in
both cases (just like it was defined
https://docs.python.org/3/library/stdtypes.html#definition.__name__),
whereas I think either it should have returned '<lambda>' and 'x' or a
new function/attribute should exist that does so and more.
For example, consider:
>>> x_1 = 1
>>> x_2 = 1
>>> x_3 = 1
>>> x_4 = x_1
>>> for i in [x_1, x_2, x_3, x_4]:
>>> print(i)
1
1
1
1
Now assume such a function exist and is called name
. Then:
>>> name(1)
'1'
>>> name("Something")
"Something"
>>> name(x_1)
'x_1'
>>> name(x_4)
'x_4'
>>> name(x_5)
'x_5' # Or an Exception!
>>> def itername(collection):
>>> for i in map(lambda x: name(x), collection):
>>> yield i
>>>
>>> for i in [x_1, x_2, x_3, x_4]:
>>> print(i, name(i))
1, 'i'
1, 'i'
1, 'i'
1, 'i'
>>> for i in itername([x_1, x_2, x_3, x_4]):
>>> print(i)
'x_1'
'x_2'
'x_3'
'x_4'
[snip]
That's not correct.
Look at the definition of 'itername'. The lambda returns the result of name(x), which is 'x'.
Therefore, the correct result is:
'x' 'x' 'x' 'x'
>
[snip] That's not correct. Look at the definition of 'itername'. The lambda returns the result of name(x), which is 'x'. Therefore, the correct result is: 'x' 'x' 'x' 'x'
You're absolutely right! It should be changed to:
def itername(collection):
for i in map(name, collection):
yield i
Hmm. So... after x = f, f.__name__ would be different from x.__name__?
Yes.
I should have written my initial email more carefully! There's another mistake:
However, as you can see __name__
special method returns 'lambda' in
both
cases (just like it was defined https://docs.python.org/3/ library/stdtypes.html#definition.__name__), whereas I think either it should have returned '<lambda>' and 'x' or a new function/attribute should exist that does so and more.
It'd be inconsistent to say x.__name__ should return 'x' and f.__name__
should return '<lambda>'. To avoid further confusion of name
the
function
with __name__
, I take back what I said about __name__
attribute.
However I can't think of an inconsistency with a builtin function called
name
or quote
or alike that behaves as described previously
(name(x)
would be 'x' and name(f) would be 'f' and name ("hello") would be "hello"
etc.) and still appreciate any input on it.
On Sun, Jun 18, 2017 at 3:24 PM, MRAB python@mrabarnett.plus.com wrote:
On 2017-06-18 22:38, Alireza Rafiei wrote:
Hi all,
I'm not sure whether this idea has been discussed before or not, so I apologize in advanced if that's the case.
Consider the behavior:
>>> f = lambda: True
>>> f.__name__
'<lambda>'
>>> x = f
>>> x.__name__
'<lambda>'
I'm arguing the behavior above is too brittle/limited and, considering
that the name of the attribute is __name__
, not entirely consistent with
Python's AST. Consider:
>>> f = lambda: True
>>> x = f
At the first line, an ast.Assign would be created whose target is an
ast.Name whose id
is f
.
At the second line, an ast.Assign would be created whose target is an
ast.Name whose id
is x
.
However, as you can see __name__
special method returns 'lambda' in
both cases (just like it was defined https://docs.python.org/3/libr
ary/stdtypes.html#definition.__name__), whereas I think either it should
have returned '<lambda>' and 'x' or a new function/attribute should exist
that does so and more.
For example, consider:
>>> x_1 = 1
>>> x_2 = 1
>>> x_3 = 1
>>> x_4 = x_1
>>> for i in [x_1, x_2, x_3, x_4]:
>>> print(i)
1
1
1
1
Now assume such a function exist and is called name
. Then:
>>> name(1)
'1'
>>> name("Something")
"Something"
>>> name(x_1)
'x_1'
>>> name(x_4)
'x_4'
>>> name(x_5)
'x_5' # Or an Exception!
>>> def itername(collection):
>>> for i in map(lambda x: name(x), collection):
>>> yield i
>>>
>>> for i in [x_1, x_2, x_3, x_4]:
>>> print(i, name(i))
1, 'i'
1, 'i'
1, 'i'
1, 'i'
>>> for i in itername([x_1, x_2, x_3, x_4]):
>>> print(i)
'x_1'
'x_2'
'x_3'
'x_4'
[snip]
That's not correct.
Look at the definition of 'itername'. The lambda returns the result of name(x), which is 'x'.
Therefore, the correct result is:
'x' 'x' 'x' 'x'
Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
On Mon, Jun 19, 2017 at 8:47 AM, Alireza Rafiei
alireza.rafiei94@gmail.com wrote:
Hmm. So... after x = f, f.__name__ would be different from x.__name__?
Yes.
There's a couple of major problems with that. The first is that, in Python, there is absolutely no difference between accessing an object via one form and via another. For example:
x = object() # or anything else y = [x, x, x] z = x q = {"spam": x} probably = globals()["x"]
You can access y[0], z, q["spam"], and (most likely) probably, and they're all the same thing. Exactly the same object. So there's no way to do attribute access on that object and get different results.
The second problem is that the current behaviour is extremely important. One such place is with function decorators, which frequently need to know the name of the function being worked on:
def command(func): parser.add_parser(func.__name__) ...
@command def spaminate(): ...
Inside the decorator, "func.__name__" has to be the name of the function being decorated ("spaminate"), not "func". The function has an identity and a canonical name. Disrupting that would cause major difficulties for these kinds of decorators.
ChrisA
Thanks for the explanation!
On Sun, Jun 18, 2017 at 4:00 PM, Chris Angelico rosuav@gmail.com wrote:
On Mon, Jun 19, 2017 at 8:47 AM, Alireza Rafiei
alireza.rafiei94@gmail.com wrote:
Hmm. So... after x = f, f.__name__ would be different from x.__name__?
Yes.
There's a couple of major problems with that. The first is that, in Python, there is absolutely no difference between accessing an object via one form and via another. For example:
x = object() # or anything else y = [x, x, x] z = x q = {"spam": x} probably = globals()["x"]
You can access y[0], z, q["spam"], and (most likely) probably, and they're all the same thing. Exactly the same object. So there's no way to do attribute access on that object and get different results.
The second problem is that the current behaviour is extremely important. One such place is with function decorators, which frequently need to know the name of the function being worked on:
def command(func): parser.add_parser(func.__name__) ...
@command def spaminate(): ...
Inside the decorator, "func.__name__" has to be the name of the function being decorated ("spaminate"), not "func". The function has an identity and a canonical name. Disrupting that would cause major difficulties for these kinds of decorators.
ChrisA
Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/