-
Notifications
You must be signed in to change notification settings - Fork 234
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Decide whether omitted return annotation means ->Any or ->None #65
Comments
-> Any
or -> None
Do you want responses here or in JukkaL/mypy#604 ? My view is that a return type is required everywhere except for |
(Please use backticks around dunder methods since otherwise GitHub interprets them as boldface.) Since the mypy issue is now closed let's discuss this here. The TypeError from However, I am actually quite undecided about what should be done here. @JukkaL has argued (in python/mypy#604) that None is a very common return value, esp. for argument-less methods. But the rule that a method is only type-checked if it has at least one annotation is pretty awkward when combined with a default rule for the return annotation, since it would seem that
would be type-checked, while
would not be type-checked. Perhaps it would not be so bad if we made a straightforward rule that you either have to have no annotations at all, or annotate all arguments (except for the first argument, if it's an instance or class method) and the return value. That's pretty much the only rule that doesn't have awkward edge cases, even if it requires you to annotate |
My Python 2.7.5 gave me this error message from
As far as I know this doesn't have any 3.5 stuff backported to it. Anyway, I might be blind, but I didn't see a section in PEP484 that gave the rules for when type checking happens or not (in fact, it seems like a "non-goal" according to the PEP). Although I don't really care because our type inferencer would take def foo(self):
return 42 and turn it into def foo(self) -> int:
return 42 It would also turn the other example into def foo(self, arg: int) -> int:
return arg+1 |
Ah, it's new in 3.5 but also in 2.7 somehow. I can't keep up. :-) The only explicit non-goals currently mentioned in the PEP are runtime checks or changing Python to require type annotations. The PEP is still a draft, and specifying what code should be considered by the type checker is definitely on my agenda. While you're right that simple toy examples like you show can easily be solved by type inferencing, this is not generally true for real-world code. I'm sure you know that many developers tend to just fix what their toolchain tells them to fix. I would like to start out with a simple rule that gives developers confidence that they can start adding annotations to their code gradually, and they won't be sucked into having to correctly annotate everything, only to find they've gone down the rabbit hole and can't dig themselves out. (I've been there several times with C++ const-correctness.) |
I'm working on a workflow design for a type inferencer. The general idea is that the programmer would start with no annotations and the inferencer would create annotations for everything (even the trivial ones you described) and add them to the source code. There's more to it than that, of course, because the programmer might need to adjust the annotations (e.g., change |
Sounds like we're in violent agreement. But what about |
I would avoid the question of If most type annotations are generated by automation, the slight extra verbosity won't require the programmer doing any extra work. (Assuming the type inferencer does a good job.) |
I want to require an explicit
Now remove the arg:
If we had the (@pludemann: I understand you don't care because you'd check them anyway -- but that's non-conformant behavior that you can document separately.) |
Simple. Consistent. Good. |
Jukka, Mark, and myself believe that the default should be |
OK. I probably wouldn't have brought this up if there hadn't been a bug in mypy (now fixed) regarding the return type of |
@vlasovskikh How is this "consistent with arguments without type annotations"? If there's no type annotation at all, I can see the argument; but if there's some annotation, then I don't think it applies. Python's default And if there's a partial annotation of args, the default arg should be but if there's no signature at all for |
@pludemann I mean consistent in a way that an argument without a type annotation has type |
I'm fine with requiring an explicit return type if there is at least one argument with an annotation, as the implicit I don't like |
@vlasovskikh The "compatibility" rules for args and return-value are different. This will no doubt confuse people, but I don't see an alternative beyond requiring invariance for args and return types, and we don't want that. @JukkaL I want the type checker to be find the most errors, so |
@pludemann The reason why I don't like |
@JukkaL But @matthiaskramm and I independently came up with If both |
Sounds like there are slightly different objectives here. PEP 484 and mypy are specifically focused on Gradual Typing (a.k.a. the "keep Raymond Hettinger happy" program :-). However Peter/Google is interested in doing the best possible job of inferring all types (or maybe finding all type bugs, or something like that). I feel that this explains why the different groups prefer different defaults. However in practice I doubt it will matter much -- we should recommend that users write explicit hints for all arguments and for the return type anyway (or omit them entirely). When the user writes a partially annotated function, Peter wants to make their life as painful as possible (make the defaults so that the developer is compelled to add the type hints by the error messages due to the default assumption), while Jukka wants mypy to shut up about areas of the code where the user has given no specific guidance. I don't want to leave this entirely up to the tool, but I do think it would be reasonable if Google's type checker emitted warnings about functions with incomplete annotations while mypy would assume a default of In the end I think it's up to @markshannon to decide, but my money is on gradual typing, with defaults to |
Why must type hints be all or nothing, even at the function level? For example, if part "number" is a string, rather than a number, I may wish to annotate that -- and the very fact that such annotations are rare will cause it to stand out for readers.
vs
which will cause me to try gliding over and ignoring the signature when I'm skimming, because it just became too noisy. If a type checker really can't infer the return type from most of my functions, then I don't really have much reason to trust its judgment anyhow -- but I don't like being told that adding the occasional hint is actually wrong. FWIW, I'm influenced by my memories of Common Lisp. Pretty much anything could be typed, and it might help the compiler. Pretty much nothing was actually typed in practice, unless there was a reason to do it -- so just knowing that someone had bothered to provide explicit type information was often more valuable than the type information itself. |
Are you saying that if you see
then it should be interpreted as
or
? The question is more interesting if the method is something other than
Would you want these interpreted as
? If not, how (other than using a type inferencer on the source code) would you get appropriate "defaults"? |
Actually, for SHOULD, my interpretation of: class Part:
def __init__(self, partno:str, name, desc="") is only that A type checker is free to complain that the definition is incomplete, but nothing stronger than a local style guide should suggest that the incompleteness is actually wrong. A better type checker MAY make additional inferences (with varying degrees of confidence), such as that desc should be a string, or even that name should be a string based on how it is actually used in the function. But failing to do so is not a spec violation; it is simply an inferior quality of implementation. |
I think we're scraping the bottom of the barrel here. Assuming there are any annotations at all the default for un-annotated arguments or return value should be Any. Type checkers may try to point out bugs but they will have to be very conservative to avoid false positives. IMO false positives are a bigger problem than false negatives -- if the type checker is wrong too often users get annoyed and simply turn it off. If it misses some bugs, well, type checking can't replace testing (see Gary Bernhardt's keynote at PyCon). |
JimJJewett -- I think you missed my point. The type checker or inferencer must interpret a missing annotation (it can also complain that an annotation is missing, of course). The possibilities seem to be:
There are good reasons for all of these, so I would prefer that the type annotations be explicit. If they're not explicit, I don't like the interpretation being "implementation defined" because interpreting an annotation would then require knowing what tool it was intended to be used with. [Note: if an annotation is missing entirely, that's different. I'm only talking about partial annotations.] If people don't want explicit types everywhere, then the consensus (with my dissent) seems to be that the default interpretation should be I agree with Guido's concerns about false positives. That's why we're trying some experiments to see what seems best. Unfortunately, it'll be a while (probably months) before our tools will be good enough for running some experiments. |
The 4th possibility is "unspecified". It differs from "Any" only in that a checker is allowed (and may be able) to infer something on its own. To me, the key point is that if someone writes:
then neither:
nor:
is any real improvement, and they are worse for a human reader. So I don't want a language standard saying that the first line is invalid and pushing people towards one of the noisier spellings. I would feel less strongly if that all-or-nothing requirement was at least explicitly limited to stub/interface files. |
Where does the PEP say that the first line is invalid? |
Where does the PEP say that the first line is invalid? Currently lines 105-109: |
Thanks, I've updated that to merely recommend this. |
Also, I wish to close this issue but I currently can't find where the PEP explicitly states that the default annotation is Any. |
So, if the return type isn't specified, it means The paragraph still doesn't say that unannotated arguments are treated as |
Correct, an omitted return type means we're not type checking that, and we're not claiming anything about the return type. I'm updating the PEP (in this repo) to say
|
See python/mypy#604
The text was updated successfully, but these errors were encountered: