Python’s built-in set type has the following characteristics: Sets are unordered. Set elements are unique. Duplicate elements are not allowed. A set itself may be modified, but the elements contained in the set must be of an immutable type. Let’s see what all that means, and how you can work with sets in Python. A set can be created in two ...
The previous section gave you a little taste of what type checking in Python looks like. You also saw an example of one of the advantages of adding types to your code: type hints help catch certain errors. Other advantages include: Type hints help document your code. Traditionally, you would use docstrings if you wanted to document the expected types of a function’s arguments. This works ...
is the type for the NoneType object, which is an object that indicates no value. None is the return value of functions that "don't return anything". It is also a common default return value for functions that search for something and may or may not find it; for example, it's returned by None when the regex doesn't match, or re.search when the key has no entry in the dict. You cannot add dict.get to strings or other objects.None
One of your variables is , not a string. Maybe you forgot to None in one of your functions, or maybe the user didn't provide a command-line option and return gave you optparse for that option's value. When you try to add None to a string, you get that exception:None
send_command(child, SNMPGROUPCMD + group + V3PRIVCMD)
One of or group or SNMPGROUPCMD has V3PRIVCMD as its value.None
So how can I question a variable that is a NoneType?
Use operator, like thisis
if variable is None:
Why this works?
Since is the sole singleton object of None in Python, we can use NoneType operator to check if a variable has is in it or not.None
Quoting from docs,is
The operators
andistest for object identity:is notis true if and only ifx is yandxare the same object.yyields the inverse truth value.x is not y
Since there can be only one instance of , None would be the preferred way to check is.None
Hear it from the horse's mouth
Quoting Python's Coding Style Guidelines - PEP-008 (jointly defined by Guido himself),
Comparisons to singletons like
should always be done withNoneoris, never the equality operators.is not
First of all, you need instead of and:or
if not isinstance(id, (int, )) and id is not None:
raise AttributeError('must be called with a id of type INT or NONE')
Explanation: you're checking to see if the variable is both not an and not int, because as you said, checking either one or the other is always NoneTrue
If you prefer to narrow it down to a single check you can do this:
if not isinstance(id, (int, type(None))):
raise AttributeError('must be called with a id of type INT or NONE')
Note: you're shadowing the builtin function with that name, try to use a different one to avoid other weird errorsid
just happens to not automatically be in the global scope. This isn't really a problem.NoneType
>>> NoneType = type(None)
>>> x = None
>>> type(x) == NoneType
True
>>> isinstance(x, NoneType)
True
In any case it would be unusual to do a type check. Rather you should test .x is None
The answer is explained here.
To quote:
A class is free to implement comparison any way it chooses, and it can choose to make comparison against None mean something (which actually makes sense; if someone told you to implement the None object from scratch, how else would you get it to compare True against itself?).
Practically-speaking, there is not much difference since custom comparison operators are rare. But you should use as a general rule.is None
Well, in Python 2, or 3.10+, you can import it from the module:types
from types import NoneType
but it's not actually implemented there or anything. just does types.py. You might as well just use NoneType = type(None) directly.type(None)
For some reason, they decided to take the name out in Python 3, before putting it back in 3.10. On versions where the name doesn't exist, just use types.NoneType.type(None)
If shows type(None) for you, rather than something like NoneType, you're probably on some nonstandard interpreter setup, such as IPython. It'd usually show up as something like <class 'NoneType'>, making it clearer that you can't just type <class 'NoneType'> and get the type.NoneType
is a shorthand notation for Optional[...], telling the type checker that either an object of the specific type is required, or Union[..., None] is required. None stands for any valid type hint, including complex compound types or a ... of more types. Whenever you have a keyword argument with default value Union[], you should use None. (Note: If you are targeting Python 3.10 or newer, PEP 604 introduced a better syntax, see below).Optional
So for your two examples, you have and dict container types, but the default value for the list keyword argument shows that a is permitted too so use None:Optional[...]
from typing import Optional
def test(a: Optional[dict] = None) -> None:
#print(a) ==> {'a': 1234}
#or
#print(a) ==> None
def test(a: Optional[list] = None) -> None:
#print(a) ==> [1, 2, 3, 4, 'a', 'b']
#or
#print(a) ==> None
There is technically no difference between using on a Optional[], or just adding Union[] to the None. So Union[] and Optional[Union[str, int]] are exactly the same thing.Union[str, int, None]
Personally, I'd stick with always using when setting the type for a keyword argument that uses Optional[] to set a default value, this documents the reason why = None is allowed better. Moreover, it makes it easier to move the None part into a separate type alias, or to later remove the Union[...] part if an argument becomes mandatory.Optional[...]
For example, say you have
from typing import Optional, Union
def api_function(optional_argument: Optional[Union[str, int]] = None) -> None:
"""Frob the fooznar.
If optional_argument is given, it must be an id of the fooznar subwidget
to filter on. The id should be a string, or for backwards compatibility,
an integer is also accepted.
"""
then documentation is improved by pulling out the into a type alias:Union[str, int]
from typing import Optional, Union
# subwidget ids used to be integers, now they are strings. Support both.
SubWidgetId = Union[str, int]
def api_function(optional_argument: Optional[SubWidgetId] = None) -> None:
"""Frob the fooznar.
If optional_argument is given, it must be an id of the fooznar subwidget
to filter on. The id should be a string, or for backwards compatibility,
an integer is also accepted.
"""
The refactor to move the into an alias was made all the much easier because Union[] was used instead of Optional[...]. The Union[str, int, None] value is not a 'subwidget id' after all, it's not part of the value, None is meant to flag the absence of a value.None
Side note: Unless your code only has to support Python 3.9 or newer, you want to avoid using the standard library container types in type hinting, as you can't say anything about what types they must contain. So instead of and dict, use list and typing.Dict, respectively. And when only reading from a container type, you may just as well accept any immutable abstract container type; lists and tuples are typing.List objects, while Sequence is a dict type:Mapping
from typing import Mapping, Optional, Sequence, Union
def test(a: Optional[Mapping[str, int]] = None) -> None:
"""accepts an optional map with string keys and integer values"""
# print(a) ==> {'a': 1234}
# or
# print(a) ==> None
def test(a: Optional[Sequence[Union[int, str]]] = None) -> None:
"""accepts an optional sequence of integers and strings
# print(a) ==> [1, 2, 3, 4, 'a', 'b']
# or
# print(a) ==> None
In Python 3.9 and up, the standard container types have all been updated to support using them in type hints, see PEP 585. But, while you now can use or dict[str, int], you still may want to use the more expressive list[Union[int, str]] and Mapping annotations to indicate that a function won't be mutating the contents (they are treated as 'read only'), and that the functions would work with any object that works as a mapping or sequence, respectively.Sequence
Python 3.10 introduces the union operator into type hinting, see PEP 604. Instead of | you can write Union[str, int]. In line with other type-hinted languages, the preferred (and more concise) way to denote an optional argument in Python 3.10 and up, is now str | int, e.g. Type | None or str | None.list | None