0% found this document useful (0 votes)
31 views8 pages

Understanding the Pass Keyword in Python

The pass statement in Python does nothing and is used as a placeholder when a statement is required but no action is needed. It can be used to create minimal classes or functions as placeholders while code is still being worked on. Match statements were introduced in Python to provide pattern matching functionality similar to switch statements in other languages. Match allows comparing a value against patterns and extracting components into variables. Patterns can be literals, variables, classes, sequences, mappings, guards, or wildcards. Functions are defined using the def keyword and allow encapsulating reusable code and introducing a new local symbol table. Functions can return values using the return statement.

Uploaded by

Dipak Nandeshwar
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
31 views8 pages

Understanding the Pass Keyword in Python

The pass statement in Python does nothing and is used as a placeholder when a statement is required but no action is needed. It can be used to create minimal classes or functions as placeholders while code is still being worked on. Match statements were introduced in Python to provide pattern matching functionality similar to switch statements in other languages. Match allows comparing a value against patterns and extracting components into variables. Patterns can be literals, variables, classes, sequences, mappings, guards, or wildcards. Functions are defined using the def keyword and allow encapsulating reusable code and introducing a new local symbol table. Functions can return values using the return statement.

Uploaded by

Dipak Nandeshwar
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

The pass statement does nothing.

It can be used when a statement is required syntactically but the


program requires no action. For example:

>>>

>>> while True:

... pass # Busy-wait for keyboard interrupt (Ctrl+C)

...

This is commonly used for creating minimal classes:

>>>

>>> class MyEmptyClass:

... pass

...

Another place pass can be used is as a place-holder for a function or conditional body when you are
working on new code, allowing you to keep thinking at a more abstract level. The pass is silently
ignored:

>>>

>>> def initlog(*args):

... pass # Remember to implement this!

...

4.6. match Statements

A match statement takes an expression and compares its value to successive patterns given as one
or more case blocks. This is superficially similar to a switch statement in C, Java or JavaScript (and
many other languages), but it can also extract components (sequence elements or object attributes)
from the value into variables.

The simplest form compares a subject value against one or more literals:

def http_error(status):

match status:

case 400:

return "Bad request"


case 404:

return "Not found"

case 418:

return "I'm a teapot"

case _:

return "Something's wrong with the internet"

Note the last block: the “variable name” _ acts as a wildcard and never fails to match. If no case
matches, none of the branches is executed.

You can combine several literals in a single pattern using | (“or”):

case 401 | 403 | 404:

return "Not allowed"

Patterns can look like unpacking assignments, and can be used to bind variables:

# point is an (x, y) tuple

match point:

case (0, 0):

print("Origin")

case (0, y):

print(f"Y={y}")

case (x, 0):

print(f"X={x}")

case (x, y):

print(f"X={x}, Y={y}")

case _:

raise ValueError("Not a point")

Study that one carefully! The first pattern has two literals, and can be thought of as an extension of
the literal pattern shown above. But the next two patterns combine a literal and a variable, and the
variable binds a value from the subject (point). The fourth pattern captures two values, which makes
it conceptually similar to the unpacking assignment (x, y) = point.
If you are using classes to structure your data you can use the class name followed by an argument
list resembling a constructor, but with the ability to capture attributes into variables:

class Point:

x: int

y: int

def where_is(point):

match point:

case Point(x=0, y=0):

print("Origin")

case Point(x=0, y=y):

print(f"Y={y}")

case Point(x=x, y=0):

print(f"X={x}")

case Point():

print("Somewhere else")

case _:

print("Not a point")

You can use positional parameters with some builtin classes that provide an ordering for their
attributes (e.g. dataclasses). You can also define a specific position for attributes in patterns by
setting the __match_args__ special attribute in your classes. If it’s set to (“x”, “y”), the following
patterns are all equivalent (and all bind the y attribute to the var variable):

Point(1, var)

Point(1, y=var)

Point(x=1, y=var)

Point(y=var, x=1)

A recommended way to read patterns is to look at them as an extended form of what you would put
on the left of an assignment, to understand which variables would be set to what. Only the
standalone names (like var above) are assigned to by a match statement. Dotted names (like
[Link]), attribute names (the x= and y= above) or class names (recognized by the “(…)” next to them
like Point above) are never assigned to.
Patterns can be arbitrarily nested. For example, if we have a short list of points, we could match it
like this:

match points:

case []:

print("No points")

case [Point(0, 0)]:

print("The origin")

case [Point(x, y)]:

print(f"Single point {x}, {y}")

case [Point(0, y1), Point(0, y2)]:

print(f"Two on the Y axis at {y1}, {y2}")

case _:

print("Something else")

We can add an if clause to a pattern, known as a “guard”. If the guard is false, match goes on to try
the next case block. Note that value capture happens before the guard is evaluated:

match point:

case Point(x, y) if x == y:

print(f"Y=X at {x}")

case Point(x, y):

print(f"Not on the diagonal")

Several other key features of this statement:

Like unpacking assignments, tuple and list patterns have exactly the same meaning and actually
match arbitrary sequences. An important exception is that they don’t match iterators or strings.

Sequence patterns support extended unpacking: [x, y, *rest] and (x, y, *rest) work similar to
unpacking assignments. The name after * may also be _, so (x, y, *_) matches a sequence of at least
two items without binding the remaining items.
Mapping patterns: {"bandwidth": b, "latency": l} captures the "bandwidth" and "latency" values from
a dictionary. Unlike sequence patterns, extra keys are ignored. An unpacking like **rest is also
supported. (But **_ would be redundant, so it not allowed.)

Subpatterns may be captured using the as keyword:

case (Point(x1, y1), Point(x2, y2) as p2): ...

will capture the second element of the input as p2 (as long as the input is a sequence of two points)

Most literals are compared by equality, however the singletons True, False and None are compared
by identity.

Patterns may use named constants. These must be dotted names to prevent them from being
interpreted as capture variable:

from enum import Enum

class Color(Enum):

RED = 0

GREEN = 1

BLUE = 2

match color:

case [Link]:

print("I see red!")

case [Link]:

print("Grass is green")

case [Link]:

print("I'm feeling the blues :(")

For a more detailed explanation and additional examples, you can look into PEP 636 which is written
in a tutorial format.

4.7. Defining Functions

We can create a function that writes the Fibonacci series to an arbitrary boundary:
>>>

>>> def fib(n): # write Fibonacci series up to n

... """Print a Fibonacci series up to n."""

... a, b = 0, 1

... while a < n:

... print(a, end=' ')

... a, b = b, a+b

... print()

...

>>> # Now call the function we just defined:

... fib(2000)

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

The keyword def introduces a function definition. It must be followed by the function name and the
parenthesized list of formal parameters. The statements that form the body of the function start at
the next line, and must be indented.

The first statement of the function body can optionally be a string literal; this string literal is the
function’s documentation string, or docstring. (More about docstrings can be found in the section
Documentation Strings.) There are tools which use docstrings to automatically produce online or
printed documentation, or to let the user interactively browse through code; it’s good practice to
include docstrings in code that you write, so make a habit of it.

The execution of a function introduces a new symbol table used for the local variables of the
function. More precisely, all variable assignments in a function store the value in the local symbol
table; whereas variable references first look in the local symbol table, then in the local symbol tables
of enclosing functions, then in the global symbol table, and finally in the table of built-in names.
Thus, global variables and variables of enclosing functions cannot be directly assigned a value within
a function (unless, for global variables, named in a global statement, or, for variables of enclosing
functions, named in a nonlocal statement), although they may be referenced.

The actual parameters (arguments) to a function call are introduced in the local symbol table of the
called function when it is called; thus, arguments are passed using call by value (where the value is
always an object reference, not the value of the object). 1 When a function calls another function, or
calls itself recursively, a new local symbol table is created for that call.
A function definition associates the function name with the function object in the current symbol
table. The interpreter recognizes the object pointed to by that name as a user-defined function.
Other names can also point to that same function object and can also be used to access the function:

>>>

>>> fib

<function fib at 10042ed0>

>>> f = fib

>>> f(100)

0 1 1 2 3 5 8 13 21 34 55 89

Coming from other languages, you might object that fib is not a function but a procedure since it
doesn’t return a value. In fact, even functions without a return statement do return a value, albeit a
rather boring one. This value is called None (it’s a built-in name). Writing the value None is normally
suppressed by the interpreter if it would be the only value written. You can see it if you really want
to using print():

>>>

>>> fib(0)

>>> print(fib(0))

None

It is simple to write a function that returns a list of the numbers of the Fibonacci series, instead of
printing it:

>>>

>>> def fib2(n): # return Fibonacci series up to n

... """Return a list containing the Fibonacci series up to n."""

... result = []

... a, b = 0, 1

... while a < n:

... [Link](a) # see below

... a, b = b, a+b

... return result

...
>>> f100 = fib2(100) # call it

>>> f100 # write the result

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

This example, as usual, demonstrates some new Python features:

The return statement returns with a value from a function. return without an expression argument
returns None. Falling off the end of a function also returns None.

The statement [Link](a) calls a method of the list object result. A method is a function that
‘belongs’ to an object and is named [Link], where obj is some object (this may be an
expression), and methodname is the name of a method that is defined by the object’s type. Different
types define different methods. Methods of different types may have the same name without
causing ambiguity. (It is possible to define your own object types and methods, using classes, see
Classes) The method append() shown in the example is defined for list objects; it adds a new
element at the end of the list. In this example it is equivalent to result = result + [a], but more
efficient.

Common questions

Powered by AI

Method calls like 'append' offer several advantages when managing data structures like lists in Python. They provide an efficient and organized way to alter lists, allowing elements to be added dynamically. The 'append' method adds an element at the end of the list without creating a new list, unlike some manual methods, enhancing both performance and simplicity. Furthermore, method calls are concise and leverage Python's object-oriented features, enabling developers to manipulate list properties and behaviors directly, adhering to the list's intended use and preventing redundancy .

Python's pattern matching handles named constants by requiring them to be dotted names to prevent misinterpretation as capture variables. This is demonstrated in examples using enumerations, where naming conventions indicate that a constant rather than a variable should be matched. This approach ensures clarity in distinguishing between variables that are meant for capturing data and constants that denote specific values, preventing unintended captures and maintaining the logical consistency of pattern declarations .

In Python, variable scope within functions is controlled through symbol tables. A new local symbol table is created whenever a function is invoked, storing the local variables. Variable assignments occur first in the local symbol table, with searches for references moving outward through enclosing functions, then global, and finally built-in tables. Direct assignment to global or nonlocal variables inside functions requires the 'global' or 'nonlocal' statement. This setup means local changes don’t affect the global scope unless explicitly specified, which can prevent unintended side-effects but requires careful management when global or nonlocal access or modifications are necessary .

Patterns and subpatterns in Python are effectively used in match statements to deconstruct and bind elements from complex data structures like tuples, lists, and custom objects. They allow for detailed data extraction and can be combined with guards for conditional logic. However, pattern matching is limited by its inability to directly match iterators or strings, and sequence patterns require exact item counts to match. Additionally, while mappings like dictionaries allow key-value extraction, they ignore extra keys, and the matching process does not assign values to dotted names, attribute names, or class names, which can cause limitations in some scenarios .

The '__match_args__' attribute in Python plays a crucial role in class-based pattern matching by defining the positional parameters that can be used in patterns. This allows developers to specify expected attributes during pattern matching, enhancing precision and control. It influences the readability of patterns by creating a consistent order for attributes, enabling clear and predictable matching expressions. Consequently, it facilitates an intuitive understanding of which class attributes are being targeted, contributing to clearer and more maintainable code .

In Python, the conceptual distinction between a procedure and a function is less rigid than in some other programming languages. The Fibonacci function, while demonstrating typical function syntax, serves as an example of how even functions without explicit return statements still return a value, specifically 'None'. Unlike procedures that do not usually return values, Python functions inherently return 'None' unless another return value is specified. This highlights Python's flexibility in function definitions, where the same basic structure can cater to both value-returning tasks and procedural operations without value returns, underscoring Python's emphasis on dynamic and flexible function use .

The Fibonacci function in Python demonstrates 'call by value' by showing that argument values passed to a function are object references, rather than the objects themselves. This means that changes within the function do not affect the actual arguments, but rather the local copies that are references pointing to the same objects. This approach maintains data integrity and demonstrates that while reference is passed and local modifications can affect mutable objects, the variables referencing them remain unchanged outside the function. Thus, the function exhibits Python's method of passing arguments where variable objects can be modified, but the reference link in the local context remains unchanged .

Docstrings in Python are optional string literals that occur as the first statement in a function body, describing the function’s purpose and behavior. They serve as documentation and can be used by tools to generate online or printed manuals or enable interactive code browsing. Including docstrings is a recommended practice because it provides clarity about the function's intent and usage, facilitating code maintenance and understandability. Docstrings also enhance collaboration by making code more readable for others or for the original author when revisiting the code .

The 'pass' statement in Python serves as a placeholder in coding constructs where a statement is syntactically needed but no action is required by the program. Unlike other syntactical elements that might require implementation or perform specific tasks, 'pass' does nothing and is silently ignored during execution. This makes it useful for creating minimal classes or placeholder functions while developing code, allowing developers to structure their code without immediately implementing certain parts .

Match statements in Python function similarly to switch statements in languages like C, Java, or JavaScript, allowing for comparison of a subject value against multiple patterns. However, match statements offer enhanced capabilities, such as extracting components from values into variables and utilizing patterns that resemble unpacking assignments. They can bind variables to values from the subject and support more complex pattern matching, including the use of guards to control flow. This makes match statements more versatile than traditional switch statements, allowing for richer data decomposition and control .

You might also like