On Jan 31, 2020, at 19:30, Soni L. <fakedme...@gmail.com> wrote:
> 
> 
>> On 2020-02-01 12:00 a.m., Andrew Barnert wrote:
>> On Jan 31, 2020, at 14:51, Soni L. <fakedme...@gmail.com> wrote:
>> >>> On 2020-01-31 2:36 p.m., Andrew Barnert wrote:
>> >> That does work, but that means foo.bar has to exist and have a value 
>> >> before you look up the name. Consider these cases:
>> >>    class Spam:
>> >>        def __init__(self):
>> >>            self.eggs = 42
>> >>    print(nameof Spam.eggs) # AttributeError
>> >>    class Foo: pass
>> >>    foo0 = Foo()
>> >>    setattr(foo0, nameof foo0.bar, 42) # AttributeError
>> 
>> > All of these seem to be working exactly as I'd expect nameof to work. In 
>> > fact these are exactly how I'd prefer it to work, personally. I'm not OP 
>> > tho.
>> 
>> Really? These seem like exactly the kinds of places I’d want to use nameof 
>> (so the IDE can magically refactor for me), and I can’t do that if it raises 
>> exceptions at runtime instead of working. It only seems like the right thing 
>> for the trivial case that, as Greg Ewing says, would already work fine 
>> without a check anyway.
> 
> Yes, really. It's dynamic, so it must pay attention to the context it's being 
> used in.

Why? The name of a variable does not depend on its runtime context.

Which is a good thing, because by the time you get to that runtime context you 
don’t even _have_ a variable; there is no such thing as variables in the Python 
data model.

>> > > But here's the thing -- C# is statically checked. Python is dynamically 
>> > > checked. (and yes, Python *does* have type checking, among other things.)
>> 
>> Not so much.
>> 
>> You _can_ do dynamic type checking in Python, but 80% of the time you don’t, 
>> you just accept anything that quacks as the right type. In C#, if you pass a 
>> complex or a string to a function that wanted an int, you get a compile-time 
>> type error. Python doesn’t have any equivalent runtime error, unless you 
>> manually write code to check isinstance and raise. And even that can’t 
>> handle all types that really exist in Python—there is no way to tell if 
>> something is an Iterator[int] for example. Of course if the function tries 
>> to return param+1, that will raise a TypeError if you passed a string—but 
>> not if you passed a complex.
>> 
>> And attributes are if anything even more “ducky” than function signatures. 
>> While you _can_ restrict the set of attributes for instances of a type with 
>> a custom __setattr__ or with __slots__ or whatever, usually you don’t; most 
>> classes’ instances can have whatever attributes they want.
>> 
>> > I figured this would be the correct way to adapt a statically checked 
>> > syntactic construct into an *equivalent* dynamically checked syntactic 
>> > construct.
>> 
>> But it’s not equivalent. In all those examples I gave, you statically know 
>> whether foo.bar exists, and therefore the compiler can check that nameof is 
>> correct, but you dynamically don’t know, so the runtime cannot check that 
>> nameof is correct. It could check something significantly different, and 
>> less useful, but it can’t check the equivalent thing, because there _is_ no 
>> equivalent thing to “Foo instances have an attribute named bar” in Python, 
>> even at runtime.
>> 
>> 
> Okay here's one of the examples you gave:
> 
>     class Spam:
>         def __init__(self):
>             self.eggs = 42
>     print(nameof Spam.eggs) # AttributeError
> 
> I don't know how C# does it, exactly, *but I'd expect this to be an error!*

I don’t think it is. I don’t have a C# compiler handy, but from the spec (sadly 
the “examples” section is just “TODO”…):

> The meaning of the named_entity of a nameof_expression is the meaning of it 
> as an expression; that is, either as a simple_name, a base_access or a 
> member_access. However, where the lookup described in Simple names and Member 
> access results in an error because an instance member was found in a static 
> context, a nameof_expression produces no such error.

…

> A nameof_expression is a constant expression of type string, and has no 
> effect at runtime. Specifically, its named_entity is not evaluated, and is 
> ignored for the purposes of definite assignment analysis (General rules for 
> simple expressions). Its value is the last identifier of the named_entity 
> before the optional final type_argument_list, transformed

So an instance member in a static context is not an error, and the value is the 
name of the member, unless I’m reading something wrong.

Also, this is the same way operators like sizeof, type of, and offsetof work in 
C#, C++, and C, isn’t it?

> Additionally those languages have null, so you could do something along the 
> lines of:
> 
>     Spam dummy = null;
>     nameof dummy.eggs

How is that relevant? Clearly the result should be the string “eggs” in C#, 
right? And in my static-only version of the proposal, the same would be true in 
Python, but in your version it would be an error. And a refactoring tool should 
rename this eggs when the member is named, which is the whole point of the 
proposal. So why is doing something different from C# that breaks the point of 
the feature better?

> IDEs are very much capable of refactoring strings.

No they’re not. They have to guess at it using heuristics, which are 
complicated, and often get it wrong. Because it’s inherently ambiguous whether 
the string or substring “spam” is meant as the name of an attribute or as 
normal English text.

> On the other hand, runtime errors would benefit those of us who use e.g. 
> plain vim and no IDE.

I mostly use emacs rather than an IDE. But I can still use refactoring tools. 
There’s nothing about a refactoring tool that demands that it be built into an 
IDE just because it could be—in the same way that PyCharm integrating a static 
type checker doesn’t stop me from using mypy.

_______________________________________________
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/UQDBFJJC3TGAVGGAGDRCBTQKIDZHEVWT/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to