By: Hristo Hristov | Updated: 2022-11-02 | Comments | Related: > Python
Problem
The Python programming language has important "reserved" commands called keywords. Each keyword provides a special instruction to the interpreter. Every data professional should be familiar with all Python keywords to use them at the right time efficiently.
Solution
This Python tutorial presents the second batch of keywords grouped by function.
In the previous Python tutorial, we examined the following categories and keywords:
- Boolean Value (
True
,False
), - Conditionals (
if
,elif
,else
), - Logical
operators (
and
,or
,not
), - Membership
check (
in
), - Exception Handling (
try block
,except
,finally
,raise
) - and Loops (
for
,while loop
,break
,continue
).
In this Python tutorial, we will continue with the final set of categories and related keywords:
- Function related (
def
,lambda
,return
,yield
), - Module related (
from
,import
,as
), - Class related
(
class
,del
,is
), - Variable related (
global variable
,nonlocal
), - Coroutines (
async
,await
) - and Others (
assert
,None
,pass
).
Function Related
def lambda return yield
Starting with def keyword
, it is used to create a function:
def say_hello(): print('Hello World')
def
is short for definition. It is good practice
to name your functions with verbs and ensure that one function does one thing. Functions
that do many operations can be difficult to read and support.
On the other hand, the lambda
keyword allows the
creation of anonymous functions inline. These constructs do not need a name. Therefore,
they cannot be invoked later like a normal function. All
lambda
expressions return the function itself.
Next, the return
keyword is an important command that allows
a function to return a certain result. In the example above, our
say_hello()
function does not return anything. Instead,
it prints out a message. We can, however, make it return a string that can be later
assigned to a variable that can then be printed:
def say_hello(): return 'Hello World' result = say_hello() print(result)
For more explanations on functions, check out my tip: How to Define and Call Functions in Python.
Lastly, in this section, we have the yield
keyword.
A regular function can be converted to a generator function using the
yield
keyword:
def say_hello(): for i in range(3): yield 'Hello World'
This example creates a function that will output "Hello World" three times, one at a time. On the fourth time, there will be an error because the generator object is now empty:
The special generator object yields one result at a time instead of the whole sequence at once. To learn more, check out this handy overview of iterables vs. iterators vs. generators: Python Iterable vs. Iterator vs. Generator with Sample Code.
Module Related
from import as
This next category of keywords in the Python import system is what takes care
of working with modules. You access another module from the current one by importing
it using the import
keyword. For example:
import pandas
This import statement imports the module named pandas by first searching for the named module, then binding it to the results of that search to a name in the local scope. However, it is better and stylistically more appealing to state:
import pandas as pd
Now all classes that are part of the pandas namespace
are available in the current local namespace from the object
pd
.
Additionally, you can import a particular class from a specific module if you expect it will be the only thing you will need in the current namespaces. Therefore, it is more optimal than importing everything from the target module:
from pandas import dataframe as df
You use as
to assign an alias like the examples
so far. Also, when importing modules, it is good practice
to follow this order:
- Standard modules – e.g., sys, os, re
- Third-party modules (anything installed in Python’s site-packages directory) – e.g., mx.DateTime, ZODB, PIL.Image, etc.
- Modules you have developed locally.
Class Related
class del is
There is hardly enough space in this article to go over classes in detail. As
far as the keywords are concerned, the class
keyword
is used to create a new type of object. Once we have this type, we can create instances
of it. A class is a bundle of data and functionality,
i.e., it can both store information and perform certain actions. In the broadest
terms, the class keyword creates the new data type. For example:
class MyData: def __init__(self, table, top): self.table = table self.top = top def query(self): statement = f'SELECT top {self.top} FROM {self.table}' return statement new_data = MyData('Employees',10) query = new_data.query() print(query)
This example shows how we can use a class to:
- Make a custom object to store and construct dynamic SQL queries.
- Refer to queries by making a new instance of the custom data class.
- Store the result set in a class attribute.
In the example, we print the actual SQL statement to the console:
On the other hand, with del
,
you can delete an object:
del my_class
For example, using the object name from the previous example:
print(new_data) del new_data print(new_data)
First, we get the name and address in memory of our object. After deleting it,
we get an error. There is no object called new_data
instance of MyData
anymore:
Finally, with is
, we can check if two objects are
the same object. Here, this means pointing to the same address in memory:
new_data = MyData('Employees',10) more_data = new_data print(more_data is new_data) print(isinstance(new_data,MyData))
Note how the more_data
variable points to the same
object, like an optimization Python does. Therefore, when compared with
is
, the two instances return
True
. In contrast, the isinstance
built-in method tests if an object is an instance of a particular class.
Variable Related
The global
and nonlocal
keywords allow manipulating the scope of a variable. By default, all variables are
global, i.e., accessible in the current namespace. On the other hand, all variables
declared inside a function are local to the function namespace.
global
and nonlocal
allow accessing a local variable in the global scope. Consider this example:
def scope_test(): def do_local(): a = 'local var' def do_nonlocal(): nonlocal a a = 'nonlocal var' def do_global(): global a a = 'global var' a = 'var' do_local() print('After local assignment:', a) do_nonlocal() print('After nonlocal assignment:', a) do_global() print('After global assignment:', a) scope_test() print("In global scope:", a)
The output is:
The variable a
is local to both
scope_test()
and do_local()
functions. This behavior is by default, so the binding was not changed.
do_nonlocal()
, however, binds the variable identifier
to the value of the same variable in the nearest enclosing scope, which in this
case is the function do_nonlocal. Finally, the global assignment
do_global()
changes the value of the variable in the
global scope.
An important note is that the variable changes depending on the function and
when it is called. This example illustrates all
practical options. In a real scenario, the value of variable
a
will be defined based on which function was called
last.
Coroutines
Using async
and await
and the asyncio library, we can write concurrent code that can execute
faster in certain situations, e.g., working with API’s
or context managers. In general, Python code executes sequentially, i.e., one task
must be completed for another to start and complete. In a simple script, this can
hardly be a concern. However, in more complex request-response scenarios, the program’s
execution speed can be vastly improved by executing tasks concurrently and asynchronously.
Here is an example: first, we have a block of code calling the
do_smth()
function asynchronously. Then, it is the
same function called sequentially:
import asyncio import time async def do_smth(): print('hello') await asyncio.sleep(1) print('world') async def main(): await asyncio.gather(do_smth(), do_smth(), do_smth()) s = time.perf_counter() asyncio.run(main()) elapsed = time.perf_counter() - s print(f'executed in {elapsed:0.2f} s')
The result:
On the contrary, here is the sequential execution:
import time def do_smth(): print('hello') time.sleep(1) print('world') def main(): for _ in range(3): do_smth() s = time.perf_counter() main() elapsed = time.perf_counter() - s print(f'executed in {elapsed:0.2f} s')
The result:
Others
Below are keywords that do not directly belong to the other categories:
assert None pass
Starting with assert
, it is used to test and debug
the code. For example:
x = 1 assert x == 2, 'x must be 1'
If the condition returns False, AssertionError
is raised:
Next, in this category, we have None
. This is a
special type of empty value, a sort of placeholder with its own type.
None
is not 0, null, empty
string, or any other empty existing datatype or value:
x = None print(type(x))
Finally, we have pass
,
which applies to loops, conditional statements, methods, and classes. It is used
to create a placeholder for a future block of code. For example, we can name a function
in our code but leave the implementation for later:
def say_hello(): pass
In fact, a function like that will return the NoneType
:
Conclusion
In this Python keyword miniseries, we examined the remaining keywords related to modules, classes, variables, coroutines, and several other keywords. Knowing how these keywords affect your program is an important stepping stone for every Python programmer and data professional.
Next Steps
- Python keywords
- Python import system
- Python class definition syntax
- Python simple statements
- Python nonlocal explained
About the author
This author pledges the content of this article is based on professional experience and not AI generated.
View all my tips
Article Last Updated: 2022-11-02