-
Notifications
You must be signed in to change notification settings - Fork 27
Additional Notes
This part of the wiki will include material on topics that came to light after the publication date of Python in a Nutshell.
[3.11+] PYTHONSAFEPATH environment variable (or -P command-line switch) to suppress implicit adding of script directory (when invoking a script using python <script_file_name.py>) or current directory (when invoking a script by module reference using python -m <module.submodule>) to the PYTHONPATH
Although on p.50 we briefly mention dictionary unpacking, where **d inside a dict
display inserts the items of d into the display, we omitted to
mention under Sequences that *i plays a similar role for iterables
in list, tuple and set displays.
Both these unpacking features are natural extensions of the forms described in steps 1 and 2 of "Matching arguments to parameters" on p.104 with respect to function calls. The example below demonstrates the syntax:
>>> lst1 = [1, 2, 3]
>>> lst2 = ('a', 'b', 'c')
>>> ["START", *lst1, "MIDDLE", *lst2, "END"]
['START', 1, 2, 3, 'MIDDLE', 'a', 'b', 'c', 'END']
We suggest you use these forms only when required, and eschew the temptation to
write [*x] rather than list(x), for example.
While the former may save three characters it is not, or at least not yet,
sufficiently well recognised by the majority of readers to be considered
idiomatic. While superficially [*dct] seems like an attractive alternative
to list(dct.keys()), a little thought suggests the preferred form should
be list(dct), since iteration over a dictionary yields its keys.
[3.10+] TypeGuard provides a way to tell a type checker that a variable can be determined to be a particular type.
TypeGuard is a special annotation for a function that takes a single argument and returns a bool. The function must
implement some test for the type of the argument, returning True if the argument is of the desired type, and False
otherwise.
Use a TypeGuard annotated function in place of:
if isinstance(obj, SpecialType):
obj = cast(SpecialType, obj)
TypeGuard is especially appropriate when determining if a variable is of a type beyond what is
easily checked using isinstance.
def is_list_str(x_list) -> bool:
return isinstance(x_list, list) and all(isinstance(x_item, str) for x_item in x_list)
def function(a_obj):
if is_list_str(a_obj):
...
# in this section, code can be type-checked with a_obj as a list of str
TypeGuard provides a way to annotate is_list_str so that code that uses it can be type checked using the
narrower type. is_list_str would be annotated using TypeGuard as:
def is_list_str(x_list) -> TypeGuard[list[str]]:
return isinstance(x_list, list) and all(isinstance(x_item, str) for x_item in x_list)
Based on the TypeGuard annotation, type checkers can safely infer that an object that passes is_list_str
should be treated as list[str]. This kind of type check would be very difficult if only explicit isinstance
function calls were used.
For more information on TypeGuard visit the online docs.
[3.10+, CPython 3.9+] "Multiple context managers for a with statement can be enclosed in parentheses" is marked as [3.10+]. This feature was actually added in CPython 3.9 as a side-effect of introducing the new Python PEG parser. It became an official language feature in 3.10.
Table 8-7 includes the cached_property decorator in the functools module, with a footnote that this property uses a class-level lock to synchronize access to the property initializer function, with potential for performance issues in a multithreaded application. This lock is removed in Python 3.12 - if its class-level locking behavior is required, it must be implemented in the decorated function.
You can search the contents of the Appendix at https://ptmcg.pythonanywhere.com/python_nutshell_app_a_search Click the "Help" label for details on search term formats.