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.


>> These all seem more confusing than helpful—and very different from C#. If 
you explain that nameof is a mix of compile time and run time, or just explain that 
it compile to the same thing as the code as you gave, people could figure it out, but 
it still seems both weird and undesirable. Python variables just don’t have a static 
type, and even if they did, the attributes are dynamic rather than determined by the 
type anyway. And that isn’t some edge case that occasionally comes up; that Spam 
example is the usual ordinary way for a class to give its instances attributes.)
>> However, that does raise the possibility that maybe mypy (or your IDE or 
favorite other static type checker tool) should be doing the check, because Python 
variables often do have  a static type and it often does declare the variables and 
“often” may not be good enough for language semantics but it’s exactly the point of 
optional gradual type checking. So:
>>   @dataclass
>>    class Spam:
>>        eggs: int = 42
>>    spam.cheese # If your typing-aware IDE will flag this
>>    nameof spam.cheese # … it will do exactly the same here
>> Now, when you’re using mypy/etc , nameof is just like C#, and gives you 
exactly the desired benefits, but all the Python compiler has to do is emit “cheese”. 
And when you aren’t using mypy? Then it just doesn’t get checked. Same as all other 
static typing errors.
>> What happens if spam: Any, or if spam: Spam but Spam didn’t statically 
deflate its attributes? At first glance, given the way optional gradual typing 
generally works, this shouldn’t be an error. But if we think of nameof as a compile 
time operator that’s meant to act like C#, maybe it is a static typing error to use 
it on an attribute that can’t be statically checked? Or maybe a warning? I don’t 
know. Maybe that should even be left up to the type checkers as a QoI issue rather 
than defined by Python?
> > 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!*

C#, Java, etc have the concept of static vs instance variables. I'd expect referring to an instance variable from a static context (such as this nameof Spam.eggs) would result in an error. Additionally those languages have null, so you could do something along the lines of:

    Spam dummy = null;
    nameof dummy.eggs

if you really wanted to. But arguably you shouldn't, because you're doing it in the wrong context (class vs instance).

IDEs are very much capable of refactoring strings. On the other hand, runtime errors would benefit those of us who use e.g. plain vim and no IDE. I don't use an IDE. thankfully the general case is that you get runtime errors where you forget to refactor something. but sometimes, you don't. and that's where this would fit in IMO.

so I'm gonna say this proposal is completely, 100% useless for IDE users. if your IDE doesn't do quite what you want, you should add an extra plugin or two to make it do so. but this feature would be a huge win for ppl who don't use IDEs. like myself.
_______________________________________________
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/SXNWVQ6XW6CTKXABLSBJU23Z6DZUYE2N/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to