[Python-Dev] PEP 526 ready for review: Syntax for Variable and Attribute Annotations

Steven D'Aprano steve at pearwood.info
Thu Sep 1 12:21:18 EDT 2016


On Thu, Sep 01, 2016 at 04:11:05PM +0300, Koos Zevenhoven wrote:

> Maybe it's just me, but I've always thought 'def' is Python's least
> logically used keyword. It seems to come from 'define', but what is it
> about 'define' that makes it relate to functions only.

Convention.

You can't use "def" to define both functions and classes:

def function(x): ...
def Class(x): ...

is ambiguous, which is the function and which is the class? So we cannot 
avoid at least one limitation: "def is for functions, or classes, but 
not both". Given that, it isn't that weird to make the rule "def is only 
for functions".



[...]
> Note that we could then also have this:
> 
> def NAME
> 
> Which would, again for readability (see above), be a way to express
> that "there is an instance variable called X, but no type hint for
> now". I can't think of a *good* way to do this with the keyword-free
> version for people that don't use type hints.

The simplest way would be to say "go on, one type hint won't hurt, 
there's no meaningful runtime cost, just do it".

from typing import Any

class X:
    NAME: Any

Since I'm not running a type checker, it doesn't matter what hint I use, 
but Any is probably the least inaccurate.

But I think there's a better way.

Unless I've missed something, there's no way to pre-declare an instance 
attribute without specifying a type. (Even if that type is Any.) So how 
about we allow None as a type-hint on its own:

    NAME: None

as equivalent to a declaration *without* a hint. The reader, and the 
type-checker, can see that there's an instance attribute called NAME, 
but in the absense of an actual hint, the type will have to be inferred, 
just as if it wasn't declared at all.

The risk is that somebody will "helpfully" correct the "obvious typo" 
and change it to NAME = None, but I think that will usually be harmless. 
I can invent examples where they will behave differently, but they feel 
contrived to me:

class X:
    spam: None  # declaration only, without a hint

    def method(self):
        if not hasattr(self, "spam"):
            raise XError("spam not set")
        return self.spam

    def setup(self, arg):
        if hasattr(self, "spam"):
            raise XError("spam already set")
        self.spam = arg


Changing the declaration to an assignment does change the behaviour of 
the class, but I think that will be obvious when it happens.


-- 
Steve


More information about the Python-Dev mailing list