I would explicitly use the None check in the form of "if user_selected is not None:", because "if user_selected" will catch multiple other cases, such as user_selected being equal to 0 or False.
At first I was going to mildly gripe that you didn't also deal with NoReturn, but now agree that it would have just distracted in this case. Maybe another video on None vs NoReturn?
1. You managed to mix up two different things: return type and return value. It's true that if value is not specified in return statement or a function finishes without reaching a return statement, it returns value of None. That fact has nothing to do with "return type" or type annotation that you specify in the function definiton after "->". 2. Default annotation for return type is not None, but Any. That is stated directly in PEP 484 and documentation. 3. There is a weird "exception" for that: Guido managed to push an inconsistent but practical decision that for __init__ method annotation should default for None (google "Allow __init__ with signature but no return type" mypy github ticket for details). Not sure if that is written down anywhere else... 4. Consistent behaviour would be to accept NoneType as valid type annotation and to not accept None, since we are supposed to specify types and not values. But when typehints were designed, somehow adding this specific exception instead of a consistent solution was pushed. Since whole type annotation system is made like that - that looks relatively organic. :-D
To the people saying that since None is a Singleton that it is the same as NoneType, this is utterly and completely incorrect. I've written Singleton classes (a lot of them) in many different languages. I've also written classes with only static members (in C# these are known as static classes, however not all languages call them that). In neither case was the object the same as the class. First, static classes don't have any objects. Second, as a basic object oriented principle, classes and objects are two different things. One comes from the other. Python's interpreter may blur the lines a bit during interpretation but they are in fact separate concepts. Making a Singleton class normally means you grab the Singleton object from the class itself, and can call it whatever you like. You can make that Singleton instance a global and can therefore grab it directly (which is probably what Python is doing), however at no point is this instance equal to the class itself. The fact that Python demands None instead of NoneType in the type annotation is weird and is not in line with literally any other language. My guess is that they do that for ease of use, breaking consistency for readability. Also, you shouldn't be constructing your own None by using NoneType(). I'm not sure if the interpreter does any magic here to save you from pitfalls, but technically this would construct a new object of NoneType which would not be equal to the None object already given to you. Comparisons to None would then fail. Most languages prevent this by making the ctor private, something that you can't do in Python (at least that I'm aware of).
in python you can make class variables really private by putting double underscore as name prefix, e.g. "__private_var" is never accessible from outside its class
so the fact that None is an alias for NoneType and also the name of the only instance doesn't bother me, as the principle of singleton would anyways makes it redundant to call both a different name. However, not being able to explicitly write NoneType when you want is a bit weird... But acceptable for the sake of clarity and simplicity : everything related to None is None. It is just slightly confusing when you try to understand the core of python because it appears to be an exception to the neat typing system.
You are right. `NoneType` is the type or the super class for None objects in Python. ``` val = None print(isinstance(val, None)) ``` The above code will throw an error because it is interpreted as No Value, while the following code would not: ``` from types import NoneType val = None print(isinstance(val, NoneType)) ``` Thank you 😊
@@evlezzz No. The keyword `None` is actually an object of `NoneType` class. This same goes for `True` and `False` also, these are objects from `int()` as super class.
@@dipeshsamrawat7957 Word "super" makes no sense here. Superclass/subclass describes relations between classes (inheritance, basically), not between a class and it's instance.
@@evlezzz I meant to describe a group, that's why I used "superclass" word. Also, we can't name a variable as None in Python, so while it is an instance or object, it's not wrong to call it a keyword.
As `None` is a single instance, it should be of type just `None`. It behaves like a static class (class used as an instance). Similar thing I notice in pygame is that we can use `Event` class as well as `EventType` but both type annotations work same. Overriding type for a class is not useful here.