How to verify pyodbc database connection is still open?

I have Python v3.12.1 on Windows 10.

In the beginning of my program I open a connection to a pyodbc database and store the connection in an options class variable. It is stored in options.dbconn. This allows me to have one connection and reuse it in many functions, putting less stress on the database server. I have a db connection timeout set to 900 seconds.

The connection is initially opened because some functions are using that options.dbconn to read more records. But at some point I’m getting an error like “Tried to use closed connection”.

Somewhere in my program the connection is getting closed.

if I do this in the debugger p options.dbconn it doesn’t tell me if the db connection is open, it just says something like <pyodbc.Connection object at 0x00000186767DC1D0> .

How do I verify in the pdb debugger that the connection is still open?

p.s. I’m assuming the database timeout value is used when executing a single query . I did not think it would close the object after 900 seconds it is idle.

EDIT: Oh dear. If I do

Then later in the function I do

Does that also close options.dbconn ?

Is options.dbconn = conn just copying a pointer, not the actual object, like a dictionary does?

yes, assignment in python does not copy, just adds another name to the object. See copy — Shallow and deep copy operations Besides, copying a database connection probably would not work anyway, there is a lot of state involved (transactions, cursors, sockets and so on)

Confirmed. By finding an extra conn.close() in my function, and removing it, it all works fine now.

I will need to remember that detail.

TutorialsTonight Logo

Python Conditional Assignment

When you want to assign a value to a variable based on some condition, like if the condition is true then assign a value to the variable, else assign some other value to the variable, then you can use the conditional assignment operator.

In this tutorial, we will look at different ways to assign values to a variable based on some condition.

1. Using Ternary Operator

The ternary operator is very special operator in Python, it is used to assign a value to a variable based on some condition.

It goes like this:

Here, the value of variable will be value_if_true if the condition is true, else it will be value_if_false .

Let's see a code snippet to understand it better.

You can see we have conditionally assigned a value to variable c based on the condition a > b .

2. Using if-else statement

if-else statements are the core part of any programming language, they are used to execute a block of code based on some condition.

Using an if-else statement, we can assign a value to a variable based on the condition we provide.

Here is an example of replacing the above code snippet with the if-else statement.

3. Using Logical Short Circuit Evaluation

Logical short circuit evaluation is another way using which you can assign a value to a variable conditionally.

The format of logical short circuit evaluation is:

It looks similar to ternary operator, but it is not. Here the condition and value_if_true performs logical AND operation, if both are true then the value of variable will be value_if_true , or else it will be value_if_false .

Let's see an example:

But if we make condition True but value_if_true False (or 0 or None), then the value of variable will be value_if_false .

So, you can see that the value of c is 20 even though the condition a < b is True .

So, you should be careful while using logical short circuit evaluation.

While working with lists , we often need to check if a list is empty or not, and if it is empty then we need to assign some default value to it.

Let's see how we can do it using conditional assignment.

Here, we have assigned a default value to my_list if it is empty.

Assign a value to a variable conditionally based on the presence of an element in a list.

Now you know 3 different ways to assign a value to a variable conditionally. Any of these methods can be used to assign a value when there is a condition.

The cleanest and fastest way to conditional value assignment is the ternary operator .

if-else statement is recommended to use when you have to execute a block of code based on some condition.

Happy coding! 😊

Learn Python practically and Get Certified .

Popular Tutorials

Popular examples, reference materials, learn python interactively, python introduction.

  • Get Started With Python
  • Your First Python Program
  • Python Comments

Python Fundamentals

  • Python Variables and Literals
  • Python Type Conversion
  • Python Basic Input and Output
  • Python Operators

Python Flow Control

  • Python if...else Statement
  • Python for Loop

Python while Loop

Python break and continue

Python pass Statement

Python Data types

  • Python Numbers and Mathematics
  • Python List
  • Python Tuple
  • Python String
  • Python Dictionary
  • Python Functions
  • Python Function Arguments
  • Python Variable Scope
  • Python Global Keyword
  • Python Recursion
  • Python Modules
  • Python Package
  • Python Main function

Python Files

  • Python Directory and Files Management
  • Python CSV: Read and Write CSV files
  • Reading CSV files in Python
  • Writing CSV files in Python
  • Python Exception Handling
  • Python Exceptions
  • Python Custom Exceptions

Python Object & Class

  • Python Objects and Classes
  • Python Inheritance
  • Python Multiple Inheritance
  • Polymorphism in Python
  • Python Operator Overloading

Python Advanced Topics

  • List comprehension
  • Python Lambda/Anonymous Function
  • Python Iterators
  • Python Generators
  • Python Namespace and Scope
  • Python Closures
  • Python Decorators
  • Python @property decorator
  • Python RegEx

Python Date and Time

  • Python datetime
  • Python strftime()
  • Python strptime()
  • How to get current date and time in Python?
  • Python Get Current Time
  • Python timestamp to datetime and vice-versa
  • Python time Module
  • Python sleep()

Additional Topic

  • Precedence and Associativity of Operators in Python
  • Python Keywords and Identifiers
  • Python Asserts
  • Python Json
  • Python *args and **kwargs

Python Tutorials

Python Assert Statement

  • Python Looping Techniques

In computer programming, the if statement is a conditional statement. It is used to execute a block of code only when a specific condition is met. For example,

Suppose we need to assign different grades to students based on their scores.

  • If a student scores above 90 , assign grade A
  • If a student scores above 75 , assign grade B
  • If a student scores above 65 , assign grade C

These conditional tasks can be achieved using the if statement.

  • Python if Statement

An if statement executes a block of code only when the specified condition is met.

Here, condition is a boolean expression, such as number > 5 , that evaluates to either True or False .

  • If condition evaluates to True , the body of the if statement is executed.
  • If condition evaluates to False , the body of the if statement will be skipped from execution.

Let's look at an example.

Working of if Statement

  • Example: Python if Statement

Sample Output 1

If user enters 10 , the condition number > 0 evaluates to True . Therefore, the body of if is executed.

Sample Output 2

If user enters -2 , the condition number > 0 evaluates to False . Therefore, the body of if is skipped from execution.

Indentation in Python

Python uses indentation to define a block of code, such as the body of an if statement. For example,

Here, the body of if has two statements. We know this because two statements (immediately after if ) start with indentation.

We usually use four spaces for indentation in Python, although any number of spaces works as long as we are consistent.

You will get an error if you write the above code like this:

Here, we haven't used indentation after the if statement. In this case, Python thinks our if statement is empty, which results in an error.

An if statement can have an optional else clause. The else statement executes if the condition in the if statement evaluates to False .

Here, if the condition inside the if statement evaluates to

  • True - the body of if executes, and the body of else is skipped.
  • False - the body of else executes, and the body of if is skipped

Working of if…else Statement

  • Example: Python if…else Statement

If user enters 10 , the condition number > 0 evalutes to True . Therefore, the body of if is executed and the body of else is skipped.

If user enters 0 , the condition number > 0 evalutes to False . Therefore, the body of if is skipped and the body of else is executed.

  • Python if…elif…else Statement

The if...else statement is used to execute a block of code among two alternatives.

However, if we need to make a choice between more than two alternatives, we use the if...elif...else statement.

Working of if…elif…else Statement

  • Example: Python if…elif…else Statement

Here, the first condition, number > 0 , evaluates to False . In this scenario, the second condition is checked.

The second condition, number < 0 , evaluates to True . Therefore, the statements inside the elif block is executed.

In the above program, it is important to note that regardless the value of number variable, only one block of code will be executed.

  • Python Nested if Statements

It is possible to include an if statement inside another if statement. For example,

Here's how this program works.

Working of Nested if Statement

More on Python if…else Statement

In certain situations, the if statement can be simplified into a single line. For example,

This code can be compactly written as

This one-liner approach retains the same functionality but in a more concise format.

Python doesn't have a ternary operator. However, we can use if...else to work like a ternary operator in other languages. For example,

can be written as

If needed, we can use logical operators such as and and or to create complex conditions to work with an if statement.

Here, we used the logical operator and to add two conditions in the if statement.

We also used >= (comparison operator) to compare two values.

Logical and comparison operators are often used with if...else statements. Visit Python Operators to learn more.

Table of Contents

  • Introduction

Before we wrap up, let’s put your knowledge of Python if else to the test! Can you solve the following challenge?

Write a function to check whether a student passed or failed his/her examination.

  • Assume the pass marks to be 50 .
  • Return Passed if the student scored more than 50. Otherwise, return Failed .

Video: Python if...else Statement

Sorry about that.

Our premium learning platform, created with over a decade of experience and thousands of feedbacks .

Learn and improve your coding skills like never before.

  • Interactive Courses
  • Certificates
  • 2000+ Challenges

Related Tutorials

Python Tutorial

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Compressing `x if x else y` statement in Python

I'm quite acquainted with Python's ternary operator approach:

My question is very simple: without prior assignments, is there anyway to reference the term being evaluated in ( if ... ) from one of the return operands ( ... if or else ... )?

The motivation here is that sometimes I use expressions in if ... that are exactly what I'd like to have as result in the ternary operation; happens though that, for small expressions, there's no problem repeating it, but for a bit longer expressions, it goes somewhat nasty. Take this as an example:

  • variable-assignment
  • ternary-operator
  • user-friendly

Rubens's user avatar

  • 1 well, Oompa Loompa is funny! –  Muhammad Talha Akbar Commented Dec 31, 2012 at 19:46
  • @AspiringAqib we don't have the assignment, but we can still enjoy some oompa loompas (: –  Rubens Commented Dec 31, 2012 at 19:47
  • well,you got solution down there huh? –  Muhammad Talha Akbar Commented Dec 31, 2012 at 19:53
  • @AspiringAqib yep, I guess this is more than enough, and may even the best solution (: better keep on KISS 'in things (: –  Rubens Commented Dec 31, 2012 at 19:56
  • Why doesn't findNext take an optional default value, like get and the hundreds of other methods modeled after it? Then you don't need this at all. –  abarnert Commented Dec 31, 2012 at 20:02

3 Answers 3

There is no way to do this, and that's intentional. The ternary if is only supposed to be used for trivial cases.

If you want to use the result of a computation twice, put it in a temporary variable:

Once you do this, it becomes clear that you're doing something silly, and in fact the pythonic way to write this is:

And that's actually 5 fewer keystrokes than your original attempt.

If you really want to save keystrokes, you can instead do this:

But that's discouraged by many style guides, and by the BDFL.

If you're only doing this once, it's better to be more explicit. If you're doing it half a dozen times, it's trivial—and much better—to make findNext take an optional default to return instead of None , just like all those built-in and stdlib functions:

Then you can do this:

abarnert's user avatar

  • I actually have some curious tics with programming: i don't like writing more than 70 columns, and I really appreciate one-line solutions; the problem here is rather about compactness than explicit number of words. I'm accepting your answer, though, as you're answering a yes/no to my binary question. Agreeing, nonetheless, that using or, as pointed by @Ignacio is quite the best solution after all. –  Rubens Commented Dec 31, 2012 at 20:07
  • Returning None is the same as returning null , and therefore just as bad . –  user824425 Commented Dec 31, 2012 at 20:24
  • 1 @Rubens: The pythonic way to write 1-line solutions is to wrap up anything complicated in an explicit function. If you can add a defval to findNext , do so; if you can't, write a wrapper. Different languages have different idiomatic styles (e.g., in Haskell, naming a function you're only going to call once is code smell), and different languages adhere to their idioms more strongly (e.g., in perl, "There's only one way to do it" would be considered a bug, not a feature). But if you've chosen Python, you should learn idiomatic Python. –  abarnert Commented Dec 31, 2012 at 20:25
  • @Tinctorius: The None is there in the example because I assume it's what the OP's original findNext returns—just like dict.get and all of the other methods on the same model. It obviously returns something falsey, and no real result can be falsey , or the OP's code is just wrong, and I'm assuming that it isn't. At any rate, this is all irrelevant to the OP's problem. (But, as a side note: do you think Haskell's Nothing violates void safety? If not, what's the difference between Nothing and None beyond static vs. dynamic typing?) –  abarnert Commented Dec 31, 2012 at 20:29
  • @abarnert: If you have dynamic typing, then I strongly prefer the "default return value" approach. Throwing a KeyError is fine too, but people might find that that clutters the code. I don't think Haskell's Maybe violates void safety at all. A void-insecure language makes many types nullable by default. Maybe allows you to opt in into nullability. The only way Haskell is void unsafe is by its bottom values (i.e. hard-to-catch termination like undefined , or non-termination like fix id ), but to fix that, your language would become harder to use and harder to implement. –  user824425 Commented Dec 31, 2012 at 20:34

Don't use if ... else at all. Instead, take advantage of Python's coalescing operators.

Ignacio Vazquez-Abrams's user avatar

  • 2 It is certainly a shortcut , @Rubens. x or y should compile into the same code as if bool(x) then x else y . bool calls .__nonzero__() . –  user824425 Commented Dec 31, 2012 at 19:51
  • 2 You can do this, but that doesn't mean you should . If you're doing this enough times that saving 5 keystrokes matters, modify the findNext method to take a default value. Otherwise, write it explicitly. –  abarnert Commented Dec 31, 2012 at 20:03
  • 2 This kind of thing can burn you if there's anything falsy thrown into the mix. Consider [] or 'default' - this might be what you're looking for, it might not. –  Jonathan Commented Dec 10, 2020 at 14:49

If you have python 3.8 or greater, you can use the := operator. In your example, it would look like

arunkannawadi's user avatar

  • 1 Actually walrus operator introduced in Python 3.8 –  S.B Commented Jun 9, 2022 at 1:42
  • you forgot to put : before the = sign. –  S.B Commented Jun 9, 2022 at 1:45

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged python variable-assignment ternary-operator user-friendly or ask your own question .

  • The Overflow Blog
  • Where does Postgres fit in a world of GenAI and vector databases?
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites
  • What does a new user need in a homepage experience on Stack Overflow?
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • Staging Ground Reviewer Motivation

Hot Network Questions

  • Meaning of 振り回す in this context
  • Can a 2-sphere be squashed flat?
  • How much payload could the Falcon 9 send to geostationary orbit?
  • Passport Carry in Taiwan
  • Purpose of burn permit?
  • How do we reconcile the story of the woman caught in adultery in John 8 and the man stoned for picking up sticks on Sabbath in Numbers 15?
  • Why is PUT Request not allowed by default in OWASP CoreRuleSet
  • Is it possible to have a planet that's gaslike in some areas and rocky in others?
  • Why doesn't the world fill with time travelers?
  • Are carbon fiber parts riveted, screwed or bolted?
  • Input Impedance of a converter and output impedance of battery
  • What to call a test that consists of running a program with only logging?
  • Parody of Fables About Authenticity
  • What's the difference between '$var' and 'var' in an arithmetic expansion?
  • `Drop` for list of elements of different dimensions
  • Who was the "Dutch author", "Bumstone Bumstone"?
  • Historical U.S. political party "realignments"?
  • Using Thin Lens Equation to find how far 1972 Blue Marble photo was taken
  • Raspberry Screen Application
  • Topology on a module over a topological ring
  • Is there a faster way of expanding multiple polynomials with power?
  • Story where character has "boomerdisc"
  • Has the US said why electing judges is bad in Mexico but good in the US?
  • What prevents a browser from saving and tracking passwords entered to a site?

python if statement variable assignment

Conditional Statements in Python

Conditional Statements in Python

Table of Contents

Introduction to the if Statement

Python: it’s all about the indentation, what do other languages do, which is better, the else and elif clauses, one-line if statements, conditional expressions (python’s ternary operator), the python pass statement.

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Conditional Statements in Python (if/elif/else)

From the previous tutorials in this series, you now have quite a bit of Python code under your belt. Everything you have seen so far has consisted of sequential execution , in which statements are always performed one after the next, in exactly the order specified.

But the world is often more complicated than that. Frequently, a program needs to skip over some statements, execute a series of statements repetitively, or choose between alternate sets of statements to execute.

That is where control structures come in. A control structure directs the order of execution of the statements in a program (referred to as the program’s control flow ).

Here’s what you’ll learn in this tutorial: You’ll encounter your first Python control structure, the if statement.

In the real world, we commonly must evaluate information around us and then choose one course of action or another based on what we observe:

If the weather is nice, then I’ll mow the lawn. (It’s implied that if the weather isn’t nice, then I won’t mow the lawn.)

In a Python program, the if statement is how you perform this sort of decision-making. It allows for conditional execution of a statement or group of statements based on the value of an expression.

The outline of this tutorial is as follows:

  • First, you’ll get a quick overview of the if statement in its simplest form.
  • Next, using the if statement as a model, you’ll see why control structures require some mechanism for grouping statements together into compound statements or blocks . You’ll learn how this is done in Python.
  • Lastly, you’ll tie it all together and learn how to write complex decision-making code.

Ready? Here we go!

Take the Quiz: Test your knowledge with our interactive “Python Conditional Statements” quiz. You’ll receive a score upon completion to help you track your learning progress:

Interactive Quiz

Test your understanding of Python conditional statements

We’ll start by looking at the most basic type of if statement. In its simplest form, it looks like this:

In the form shown above:

  • <expr> is an expression evaluated in a Boolean context, as discussed in the section on Logical Operators in the Operators and Expressions in Python tutorial.
  • <statement> is a valid Python statement, which must be indented. (You will see why very soon.)

If <expr> is true (evaluates to a value that is “truthy”), then <statement> is executed. If <expr> is false, then <statement> is skipped over and not executed.

Note that the colon ( : ) following <expr> is required. Some programming languages require <expr> to be enclosed in parentheses, but Python does not.

Here are several examples of this type of if statement:

Note: If you are trying these examples interactively in a REPL session, you’ll find that, when you hit Enter after typing in the print('yes') statement, nothing happens.

Because this is a multiline statement, you need to hit Enter a second time to tell the interpreter that you’re finished with it. This extra newline is not necessary in code executed from a script file.

Grouping Statements: Indentation and Blocks

So far, so good.

But let’s say you want to evaluate a condition and then do more than one thing if it is true:

If the weather is nice, then I will: Mow the lawn Weed the garden Take the dog for a walk (If the weather isn’t nice, then I won’t do any of these things.)

In all the examples shown above, each if <expr>: has been followed by only a single <statement> . There needs to be some way to say “If <expr> is true, do all of the following things.”

The usual approach taken by most programming languages is to define a syntactic device that groups multiple statements into one compound statement or block . A block is regarded syntactically as a single entity. When it is the target of an if statement, and <expr> is true, then all the statements in the block are executed. If <expr> is false, then none of them are.

Virtually all programming languages provide the capability to define blocks, but they don’t all provide it in the same way. Let’s see how Python does it.

Python follows a convention known as the off-side rule , a term coined by British computer scientist Peter J. Landin. (The term is taken from the offside law in association football.) Languages that adhere to the off-side rule define blocks by indentation. Python is one of a relatively small set of off-side rule languages .

Recall from the previous tutorial on Python program structure that indentation has special significance in a Python program. Now you know why: indentation is used to define compound statements or blocks. In a Python program, contiguous statements that are indented to the same level are considered to be part of the same block.

Thus, a compound if statement in Python looks like this:

Here, all the statements at the matching indentation level (lines 2 to 5) are considered part of the same block. The entire block is executed if <expr> is true, or skipped over if <expr> is false. Either way, execution proceeds with <following_statement> (line 6) afterward.

Python conditional statement

Notice that there is no token that denotes the end of the block. Rather, the end of the block is indicated by a line that is indented less than the lines of the block itself.

Note: In the Python documentation, a group of statements defined by indentation is often referred to as a suite . This tutorial series uses the terms block and suite interchangeably.

Consider this script file foo.py :

Running foo.py produces this output:

The four print() statements on lines 2 to 5 are indented to the same level as one another. They constitute the block that would be executed if the condition were true. But it is false, so all the statements in the block are skipped. After the end of the compound if statement has been reached (whether the statements in the block on lines 2 to 5 are executed or not), execution proceeds to the first statement having a lesser indentation level: the print() statement on line 6.

Blocks can be nested to arbitrary depth. Each indent defines a new block, and each outdent ends the preceding block. The resulting structure is straightforward, consistent, and intuitive.

Here is a more complicated script file called blocks.py :

The output generated when this script is run is shown below:

Note: In case you have been wondering, the off-side rule is the reason for the necessity of the extra newline when entering multiline statements in a REPL session. The interpreter otherwise has no way to know that the last statement of the block has been entered.

Perhaps you’re curious what the alternatives are. How are blocks defined in languages that don’t adhere to the off-side rule?

The tactic used by most programming languages is to designate special tokens that mark the start and end of a block. For example, in Perl blocks are defined with pairs of curly braces ( {} ) like this:

C/C++, Java , and a whole host of other languages use curly braces in this way.

Perl conditional statement

Other languages, such as Algol and Pascal, use keywords begin and end to enclose blocks.

Better is in the eye of the beholder. On the whole, programmers tend to feel rather strongly about how they do things. Debate about the merits of the off-side rule can run pretty hot.

On the plus side:

  • Python’s use of indentation is clean, concise, and consistent.
  • In programming languages that do not use the off-side rule, indentation of code is completely independent of block definition and code function. It’s possible to write code that is indented in a manner that does not actually match how the code executes, thus creating a mistaken impression when a person just glances at it. This sort of mistake is virtually impossible to make in Python.
  • Use of indentation to define blocks forces you to maintain code formatting standards you probably should be using anyway.

On the negative side:

  • Many programmers don’t like to be forced to do things a certain way. They tend to have strong opinions about what looks good and what doesn’t, and they don’t like to be shoehorned into a specific choice.
  • Some editors insert a mix of space and tab characters to the left of indented lines, which makes it difficult for the Python interpreter to determine indentation levels. On the other hand, it is frequently possible to configure editors not to do this. It generally isn’t considered desirable to have a mix of tabs and spaces in source code anyhow, no matter the language.

Like it or not, if you’re programming in Python, you’re stuck with the off-side rule. All control structures in Python use it, as you will see in several future tutorials.

For what it’s worth, many programmers who have been used to languages with more traditional means of block definition have initially recoiled at Python’s way but have gotten comfortable with it and have even grown to prefer it.

Now you know how to use an if statement to conditionally execute a single statement or a block of several statements. It’s time to find out what else you can do.

Sometimes, you want to evaluate a condition and take one path if it is true but specify an alternative path if it is not. This is accomplished with an else clause:

If <expr> is true, the first suite is executed, and the second is skipped. If <expr> is false, the first suite is skipped and the second is executed. Either way, execution then resumes after the second suite. Both suites are defined by indentation, as described above.

In this example, x is less than 50 , so the first suite (lines 4 to 5) are executed, and the second suite (lines 7 to 8) are skipped:

Here, on the other hand, x is greater than 50 , so the first suite is passed over, and the second suite executed:

There is also syntax for branching execution based on several alternatives. For this, use one or more elif (short for else if ) clauses. Python evaluates each <expr> in turn and executes the suite corresponding to the first that is true. If none of the expressions are true, and an else clause is specified, then its suite is executed:

An arbitrary number of elif clauses can be specified. The else clause is optional. If it is present, there can be only one, and it must be specified last:

At most, one of the code blocks specified will be executed. If an else clause isn’t included, and all the conditions are false, then none of the blocks will be executed.

Note: Using a lengthy if / elif / else series can be a little inelegant, especially when the actions are simple statements like print() . In many cases, there may be a more Pythonic way to accomplish the same thing.

Here’s one possible alternative to the example above using the dict.get() method:

Recall from the tutorial on Python dictionaries that the dict.get() method searches a dictionary for the specified key and returns the associated value if it is found, or the given default value if it isn’t.

An if statement with elif clauses uses short-circuit evaluation, analogous to what you saw with the and and or operators. Once one of the expressions is found to be true and its block is executed, none of the remaining expressions are tested. This is demonstrated below:

The second expression contains a division by zero, and the third references an undefined variable var . Either would raise an error, but neither is evaluated because the first condition specified is true.

It is customary to write if <expr> on one line and <statement> indented on the following line like this:

But it is permissible to write an entire if statement on one line. The following is functionally equivalent to the example above:

There can even be more than one <statement> on the same line, separated by semicolons:

But what does this mean? There are two possible interpretations:

If <expr> is true, execute <statement_1> .

Then, execute <statement_2> ... <statement_n> unconditionally, irrespective of whether <expr> is true or not.

If <expr> is true, execute all of <statement_1> ... <statement_n> . Otherwise, don’t execute any of them.

Python takes the latter interpretation. The semicolon separating the <statements> has higher precedence than the colon following <expr> —in computer lingo, the semicolon is said to bind more tightly than the colon. Thus, the <statements> are treated as a suite, and either all of them are executed, or none of them are:

Multiple statements may be specified on the same line as an elif or else clause as well:

While all of this works, and the interpreter allows it, it is generally discouraged on the grounds that it leads to poor readability, particularly for complex if statements. PEP 8 specifically recommends against it.

As usual, it is somewhat a matter of taste. Most people would find the following more visually appealing and easier to understand at first glance than the example above:

If an if statement is simple enough, though, putting it all on one line may be reasonable. Something like this probably wouldn’t raise anyone’s hackles too much:

Python supports one additional decision-making entity called a conditional expression. (It is also referred to as a conditional operator or ternary operator in various places in the Python documentation.) Conditional expressions were proposed for addition to the language in PEP 308 and green-lighted by Guido in 2005.

In its simplest form, the syntax of the conditional expression is as follows:

This is different from the if statement forms listed above because it is not a control structure that directs the flow of program execution. It acts more like an operator that defines an expression. In the above example, <conditional_expr> is evaluated first. If it is true, the expression evaluates to <expr1> . If it is false, the expression evaluates to <expr2> .

Notice the non-obvious order: the middle expression is evaluated first, and based on that result, one of the expressions on the ends is returned. Here are some examples that will hopefully help clarify:

Note: Python’s conditional expression is similar to the <conditional_expr> ? <expr1> : <expr2> syntax used by many other languages—C, Perl and Java to name a few. In fact, the ?: operator is commonly called the ternary operator in those languages, which is probably the reason Python’s conditional expression is sometimes referred to as the Python ternary operator.

You can see in PEP 308 that the <conditional_expr> ? <expr1> : <expr2> syntax was considered for Python but ultimately rejected in favor of the syntax shown above.

A common use of the conditional expression is to select variable assignment. For example, suppose you want to find the larger of two numbers. Of course, there is a built-in function, max() , that does just this (and more) that you could use. But suppose you want to write your own code from scratch.

You could use a standard if statement with an else clause:

But a conditional expression is shorter and arguably more readable as well:

Remember that the conditional expression behaves like an expression syntactically. It can be used as part of a longer expression. The conditional expression has lower precedence than virtually all the other operators, so parentheses are needed to group it by itself.

In the following example, the + operator binds more tightly than the conditional expression, so 1 + x and y + 2 are evaluated first, followed by the conditional expression. The parentheses in the second case are unnecessary and do not change the result:

If you want the conditional expression to be evaluated first, you need to surround it with grouping parentheses. In the next example, (x if x > y else y) is evaluated first. The result is y , which is 40 , so z is assigned 1 + 40 + 2 = 43 :

If you are using a conditional expression as part of a larger expression, it probably is a good idea to use grouping parentheses for clarification even if they are not needed.

Conditional expressions also use short-circuit evaluation like compound logical expressions. Portions of a conditional expression are not evaluated if they don’t need to be.

In the expression <expr1> if <conditional_expr> else <expr2> :

  • If <conditional_expr> is true, <expr1> is returned and <expr2> is not evaluated.
  • If <conditional_expr> is false, <expr2> is returned and <expr1> is not evaluated.

As before, you can verify this by using terms that would raise an error:

In both cases, the 1/0 terms are not evaluated, so no exception is raised.

Conditional expressions can also be chained together, as a sort of alternative if / elif / else structure, as shown here:

It’s not clear that this has any significant advantage over the corresponding if / elif / else statement, but it is syntactically correct Python.

Occasionally, you may find that you want to write what is called a code stub: a placeholder for where you will eventually put a block of code that you haven’t implemented yet.

In languages where token delimiters are used to define blocks, like the curly braces in Perl and C, empty delimiters can be used to define a code stub. For example, the following is legitimate Perl or C code:

Here, the empty curly braces define an empty block. Perl or C will evaluate the expression x , and then even if it is true, quietly do nothing.

Because Python uses indentation instead of delimiters, it is not possible to specify an empty block. If you introduce an if statement with if <expr>: , something has to come after it, either on the same line or indented on the following line.

Consider this script foo.py :

If you try to run foo.py , you’ll get this:

The Python pass statement solves this problem. It doesn’t change program behavior at all. It is used as a placeholder to keep the interpreter happy in any situation where a statement is syntactically required, but you don’t really want to do anything:

Now foo.py runs without error:

With the completion of this tutorial, you are beginning to write Python code that goes beyond simple sequential execution:

  • You were introduced to the concept of control structures . These are compound statements that alter program control flow —the order of execution of program statements.
  • You learned how to group individual statements together into a block or suite .
  • You encountered your first control structure, the if statement, which makes it possible to conditionally execute a statement or block based on evaluation of program data.

All of these concepts are crucial to developing more complex Python code.

The next two tutorials will present two new control structures: the while statement and the for statement. These structures facilitate iteration , execution of a statement or block of statements repeatedly.

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About John Sturtz

John Sturtz

John is an avid Pythonista and a member of the Real Python tutorial team.

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Aldren Santos

Master Real-World Python Skills With Unlimited Access to Real Python

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

What Do You Think?

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal . Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session . Happy Pythoning!

Keep Learning

Related Topics: basics python

Recommended Video Course: Conditional Statements in Python (if/elif/else)

Keep reading Real Python by creating a free account or signing in:

Already have an account? Sign-In

python if statement variable assignment

  • Module 2: The Essentials of Python »
  • Conditional Statements
  • View page source

Conditional Statements 

There are reading-comprehension exercises included throughout the text. These are meant to help you put your reading to practice. Solutions for the exercises are included at the bottom of this page.

In this section, we will be introduced to the if , else , and elif statements. These allow you to specify that blocks of code are to be executed only if specified conditions are found to be true, or perhaps alternative code if the condition is found to be false. For example, the following code will square x if it is a negative number, and will cube x if it is a positive number:

Please refer to the “Basic Python Object Types” subsection to recall the basics of the “boolean” type, which represents True and False values. We will extend that discussion by introducing comparison operations and membership-checking, and then expanding on the utility of the built-in bool type.

Comparison Operations 

Comparison statements will evaluate explicitly to either of the boolean-objects: True or False . There are eight comparison operations in Python:

Operation

Meaning

strictly less than

less than or equal

strictly greater than

greater than or equal

equal

not equal

object identity

not

negated object identity

The first six of these operators are familiar from mathematics:

Note that = and == have very different meanings. The former is the assignment operator, and the latter is the equality operator:

Python allows you to chain comparison operators to create “compound” comparisons:

Whereas == checks to see if two objects have the same value, the is operator checks to see if two objects are actually the same object. For example, creating two lists with the same contents produces two distinct lists, that have the same “value”:

Thus the is operator is most commonly used to check if a variable references the None object, or either of the boolean objects:

Use is not to check if two objects are distinct:

bool and Truth Values of Non-Boolean Objects 

Recall that the two boolean objects True and False formally belong to the int type in addition to bool , and are associated with the values 1 and 0 , respectively:

Likewise Python ascribes boolean values to non-boolean objects. For example,the number 0 is associated with False and non-zero numbers are associated with True . The boolean values of built-in objects can be evaluated with the built-in Python command bool :

and non-zero Python integers are associated with True :

The following built-in Python objects evaluate to False via bool :

Zero of any numeric type: 0 , 0.0 , 0j

Any empty sequence, such as an empty string or list: '' , tuple() , [] , numpy.array([])

Empty dictionaries and sets

Thus non-zero numbers and non-empty sequences/collections evaluate to True via bool .

The bool function allows you to evaluate the boolean values ascribed to various non-boolean objects. For instance, bool([]) returns False wherease bool([1, 2]) returns True .

if , else , and elif 

We now introduce the simple, but powerful if , else , and elif conditional statements. This will allow us to create simple branches in our code. For instance, suppose you are writing code for a video game, and you want to update a character’s status based on her/his number of health-points (an integer). The following code is representative of this:

Each if , elif , and else statement must end in a colon character, and the body of each of these statements is delimited by whitespace .

The following pseudo-code demonstrates the general template for conditional statements:

In practice this can look like:

In its simplest form, a conditional statement requires only an if clause. else and elif clauses can only follow an if clause.

Similarly, conditional statements can have an if and an else without an elif :

Conditional statements can also have an if and an elif without an else :

Note that only one code block within a single if-elif-else statement can be executed: either the “if-block” is executed, or an “elif-block” is executed, or the “else-block” is executed. Consecutive if-statements, however, are completely independent of one another, and thus their code blocks can be executed in sequence, if their respective conditional statements resolve to True .

Reading Comprehension: Conditional statements

Assume my_list is a list. Given the following code:

What will happen if my_list is [] ? Will IndexError be raised? What will first_item be?

Assume variable my_file is a string storing a filename, where a period denotes the end of the filename and the beginning of the file-type. Write code that extracts only the filename.

my_file will have at most one period in it. Accommodate cases where my_file does not include a file-type.

"code.py" \(\rightarrow\) "code"

"doc2.pdf" \(\rightarrow\) "doc2"

"hello_world" \(\rightarrow\) "hello_world"

Inline if-else statements 

Python supports a syntax for writing a restricted version of if-else statements in a single line. The following code:

can be written in a single line as:

This is suggestive of the general underlying syntax for inline if-else statements:

The inline if-else statement :

The expression A if <condition> else B returns A if bool(<condition>) evaluates to True , otherwise this expression will return B .

This syntax is highly restricted compared to the full “if-elif-else” expressions - no “elif” statement is permitted by this inline syntax, nor are multi-line code blocks within the if/else clauses.

Inline if-else statements can be used anywhere, not just on the right side of an assignment statement, and can be quite convenient:

We will see this syntax shine when we learn about comprehension statements. That being said, this syntax should be used judiciously. For example, inline if-else statements ought not be used in arithmetic expressions, for therein lies madness:

Short-Circuiting Logical Expressions 

Armed with our newfound understanding of conditional statements, we briefly return to our discussion of Python’s logic expressions to discuss “short-circuiting”. In Python, a logical expression is evaluated from left to right and will return its boolean value as soon as it is unambiguously determined, leaving any remaining portions of the expression unevaluated . That is, the expression may be short-circuited .

For example, consider the fact that an and operation will only return True if both of its arguments evaluate to True . Thus the expression False and <anything> is guaranteed to return False ; furthermore, when executed, this expression will return False without having evaluated bool(<anything>) .

To demonstrate this behavior, consider the following example:

According to our discussion, the pattern False and short-circuits this expression without it ever evaluating bool(1/0) . Reversing the ordering of the arguments makes this clear.

In practice, short-circuiting can be leveraged in order to condense one’s code. Suppose a section of our code is processing a variable x , which may be either a number or a string . Suppose further that we want to process x in a special way if it is an all-uppercased string. The code

is problematic because isupper can only be called once we are sure that x is a string; this code will raise an error if x is a number. We could instead write

but the more elegant and concise way of handling the nestled checking is to leverage our ability to short-circuit logic expressions.

See, that if x is not a string, that isinstance(x, str) will return False ; thus isinstance(x, str) and x.isupper() will short-circuit and return False without ever evaluating bool(x.isupper()) . This is the preferable way to handle this sort of checking. This code is more concise and readable than the equivalent nested if-statements.

Reading Comprehension: short-circuited expressions

Consider the preceding example of short-circuiting, where we want to catch the case where x is an uppercased string. What is the “bug” in the following code? Why does this fail to utilize short-circuiting correctly?

Links to Official Documentation 

Truth testing

Boolean operations

Comparisons

‘if’ statements

Reading Comprehension Exercise Solutions: 

Conditional statements

If my_list is [] , then bool(my_list) will return False , and the code block will be skipped. Thus first_item will be None .

First, check to see if . is even contained in my_file . If it is, find its index-position, and slice the string up to that index. Otherwise, my_file is already the file name.

Short-circuited expressions

fails to account for the fact that expressions are always evaluated from left to right. That is, bool(x.isupper()) will always be evaluated first in this instance and will raise an error if x is not a string. Thus the following isinstance(x, str) statement is useless.

  • Subscription

Tutorial: Using If Statements in Python

Our life is full of conditions even if we don’t notice them most of the time. Let’s look at a few examples:

If tomorrow it doesn't rain, I’ll go out with my friends in the park. Otherwise, I’ll stay home with a cup of hot tea and watch TV.

If tomorrow it isn't too hot, I’ll go to the sea, but if it is, I’ll have a walk in the forest. However, if it rains, I’ll stay home.

You get the idea. Let’s see how conditions work in computers. You may already know that programs in Python are executed line by line. However, sometimes, we need to skip some code and execute only some of it only if certain conditions are met. This is where control structures become useful. Conditional statements in Python are built on these control structures. They will guide the computer in the execution of a program.

In this tutorial, you'll learn how to use conditional statements. This guide is for beginners in Python, but you'll need to know some basics of coding in Python. If you don’t, then check this free Python Fundamentals course .

Basic if Statement

In Python, if statements are a starting point to implement a condition. Let’s look at the simplest example:

When <condition> is evaluated by Python, it’ll become either True or False (Booleans). Thus, if the condition is True (i.e, it is met), the <expression> will be executed, but if <condition> is False (i.e., it is not met), the <expression> won’t be executed.

We are pretty free to decide what conditions and expressions can be because Python is very flexible.

Let’s look at a concrete example.

First of all, we define two variables, x and y . Then we say that if variable x is smaller than variable y , print out x is smaller than y ). Indeed, if we execute this code, we’ll print out this output because 3 is smaller than 10.

Output: x is smaller than y.

Let’s look at a more complex example.

In this case, if the condition is met, then a value of 13 will be assigned to the variable z . Then Variable z is now 13. will be printed out (note that the print statement can be used both outside and inside the if statement).

As you can see, we aren't restrained in the choice of an expression to execute. You can now practice more by writing more complex code.

Let’s know see what happens if we execute the following code:

Here we changed the direction of the comparison symbol (it was less than , and now it’s greater than ). Can you guess the output?

There will be no output! This happened because the condition hadn't been met. 3 is not greater than 10, so the condition evaluated to False , and the expression wasn’t executed. How do we solve this problem? With the else statement.

else Statement

What if we want to execute some code if the condition isn't met? We add an else statement below the if statement. Let’s look at an example.

Here, Python first executes the if condition and checks if it’s True . Since 3 is not greater than 10, the condition isn't met, so we don’t print out “x is greater than y.” Then we say that in all other cases we should execute the code under the else statement: x is smaller than y.

Let’s get back to our first example of a conditional statement:

Here the else statement is “Otherwise.”

What happens if the condition is met?

In this case, Python just prints out the first sentence as before.

What if x is equal to y ?

The output is clearly wrong because 3 is equal to 3! We have another condition outside the greater or less than comparison symbols; thus, we have to use the elif statement.

elif Statement

Let’s rewrite the above example and add an elif statement.

Output: x is equal to y .

Python first checks if the condition x < y is met. It isn't, so it goes on to the second condition, which in Python, we write as elif , which is short for else if . If the first condition isn't met, check the second condition, and if it’s met, execute the expression. Else, do something else. The output is “x is equal to y.”

Let’s now get back to one of our first examples of conditional statements:

Here, our first condition is that tomorrow it’s not too hot ( if statement). If this condition isn't met, then we go for a walk in the forest ( elif statement). Finally, if neither condition is met, we’ll stay home ( else statement).

Now let’s translate this sentence into Python.

In this example, we're going to use strings instead of integers to demonstrate the flexibility of the if condition in Python.

Python first checks if the variable tomorrow is equal to “warm” and if it is, then it prints out I'll go to the sea. and stops the execution. What happens if the first condition isn't met?

In this case, Python evaluates the first condition to False and goes to the second condition. This condition is True , so it prints out I'll go to the forest. and stops the execution.

If neither of the two conditions is met, then it’ll print out I’ll stay home.

Of course, you can use whatever number of elif statements you want. Let’s add more conditions and also change what is printed out under the else statement to Weather not recognized. (for example, if tomorrow is “f”, we don’t know what it means).

Guess what’s printed out?

Multiple Conditions

Let’s now add some complexity. What if we want to meet multiple conditions in one if statement?

Let’s say we want to predict a biome (i.e., desert or tropical forest) based on two climate measurements: temperature and humidity. For example, if it’s hot and dry, then it’s a hot desert, but if it’s cold and dry, then it’s an arctic desert. You can see that we cannot classify these two biomes based only on their humidity (they are both dry) so we also have to add the temperature measure.

In Python, we can use logical operators (i.e., and, or) to use multiple conditions in the same if statement.

Look at the code below.

The output will be It's a hot desert. because only when humidity is low and temperature is high, the combined condition is True . It’s not sufficient to have only one of the conditions to be True .

Formally, Python checks if the first condition of humidity is True (indeed, it is), then it checks if the second condition of temperature is True (and it is) and only in this case the combined condition is True . If at least one of these conditions isn't met, then the combined condition evaluates to False .

What if we want either of two (or more) conditions is met? In this case we should use the or logical operator.

Let’s look at an example. Say you have a list of numbers from 1 to 14 (inclusive), and you want to extract all the numbers that are smaller than 3 or greater or equal to 10. You can achieve the result using an or operator!

Output: [1, 2, 10, 11, 12, 13, 14]

Here Python checks whether the current number in the for loop is less than 3, and if it’s True , then the combined if statement evaluates to True . The same happens if the current number is equal to or greater than 10. If the combined if statement is True , then the expression is executed and the current number is appended to the list nums_less_3_greater_equal_10 .

For the sake of experiment, let’s change or to and .

In this case, the current number should be simultaneously smaller than 3 and greater or equal to 10, which is clearly not possible so the combined if statement evaluates to False and the expression isn't executed.

To make things even more clear, look at this print statement.

Output: True

Here Python evaluates the combination of False and True , and since we have the or logical operator, it’s sufficient that at least one of these Booleans is True to evaluate the combined statement to True .

Now, what happens if we change or to and ?

Output: False

Both Booleans should be True to evaluate the combined condition to True . Since one of them is False , the combined condition is also False . This is what happens in the example with numbers.

You can even combine multiple logical operators in one expression. Let’s use the same list of numbers, but now, we want to find all the numbers that are either smaller than 3 or greater or equal to 10 and simultaneously are even numbers.

Output: [2, 10, 12, 14]

Why is the first number of the output 2? In the second for loop, 2 is evaluated in the first condition in parentheses. It is smaller than 3, so the combined condition in parentheses is True . 2 is also divisible by 2 with the remainder 0, so the second condition is also True . Both conditions are True , so this number is appended to the list.

Why do we use parentheses? It’s because of the operator precedence in Python. What if we remove them?

Output: [1, 2, 10, 12, 14]

We have 1 in the list! In Python, all operators are evaluated in a precise order. For example, the and operator takes precedence over the or operator. But if we place the or operator in parentheses, it’ll take precedence over the and operator.

First we evaluate the conditions on both sides of the and operator (it has precedence). 1 is neither greater than 10 nor yields 0 if divided by 2, so the combined condition is False . We are left with the condition if num < 3 or False . 1 is smaller than 3, so the first condition is True . The condition becomes True or False . We have an or operator, so the combined condition evaluates to True , and 1 is appended to the list. Practice by checking what happens with the other numbers.

Finally, have a look at this truth table to understand how logical operators work. Here, we will describe only the and and or logical operators, but in Python, we also have the not operator. We invite you to learn more about it and practice using it inside if statements.

Input A Input B AND OR
False False False False
True False False True
False True False True
True True True True

We have two inputs, A and B, that can be either True or False . For example, in the second row, A is True , while B is False ; thus, A AND B evaluate to False but A OR B evaluate to True . The rest of the table is read in the same way. Take a minute to understand what it tells you.

Nested if Statements

Python is a very flexible programming language, and it allows you to use if statements inside other if statements, so called nested if statements . Let’s look at an example.

Output: Well done!

Here, if the mark is between 60 and 100, the expression under the if statement is executed. But then we have other conditions that are also evaluated. So, our mark is 85, which is between 60 and 100. However, 85 is smaller than 90, so the first nested if condition is False , and the first nested expression isn't executed. But 85 is higher than 80, so the second expression is executed and “Well done!” is printed out.

Of course, we also have elif statements outside the expression below the first if statement. For example, what if the mark is higher than 100? If the first condition (number between 60 and 100) is False , then we go directly to the elif statement mark > 100 and print out This mark is too low. .

Try to assign different numbers to the mark variable to understand the logic of this code.

Pattern Matching in Python 3.10

The pattern matching was added in Python 3.10, released in October, 2021. In short, it can be seen a different syntax for if..elif statements. Let's look at an example by rewrting a previous example using the pattern matching.

We can see similarities between using the if..elif statements and the match..case syntax. First, we define what variable we want to match , and when we define the cases (or values this variable can take). The rest of the code is similar. If a case is matched (that's equivalent of a double equal sign), then the print expression is executed.

Note the last case statement, it's the _ case, which is equivalent to else : if no cases are matched, then we print Weather not recognized .

pass Statement

As you start writing more complex code, you may find yourself in the situation where you have to use a placeholder instead of the code you want to implement later. The pass statement is this placeholder. Let’s look at an example with and without the pass statement.

Python expects some code under the if statement, but you are yet to implement it! You can write pass there and solve this problem.

Output: I'll write this code later.

If instead you place pass in the if statement, Python won’t throw any error and will pass to any code you have below the if statement. This works even if you have other conditions below the first if statement.

Output: The variable num is 4.

Conclusions

In Python, if statements are used all the time, and you’ll find yourself using them in basically any project or script you're building, so it's essential to understand the logic behind them. In this article, we’ve covered the most important aspects of if conditions in Python:

  • Creating basic if statements
  • Adding complexity by using else and elif statements
  • Combining multiple conditions in one if statement using logical operators ( or , and )
  • Using nested if statements
  • Using pass statements as placeholders

With this knowledge, you can now start working with conditional statements in Python.

Feel free to connect with me on LinkedIn and GitHub . Happy coding!

More learning resources

Python dictionary comprehension tutorial (with 39 code examples), tutorial: indexing dataframes in pandas.

Learn data skills 10x faster

Headshot

Join 1M+ learners

Enroll for free

  • Data Analyst (Python)
  • Gen AI (Python)
  • Business Analyst (Power BI)
  • Business Analyst (Tableau)
  • Machine Learning
  • Data Analyst (R)
  • Python »
  • 3.12.5 Documentation »
  • The Python Language Reference »
  • 7. Simple statements
  • Theme Auto Light Dark |

7. Simple statements ¶

A simple statement is comprised within a single logical line. Several simple statements may occur on a single line separated by semicolons. The syntax for simple statements is:

7.1. Expression statements ¶

Expression statements are used (mostly interactively) to compute and write a value, or (usually) to call a procedure (a function that returns no meaningful result; in Python, procedures return the value None ). Other uses of expression statements are allowed and occasionally useful. The syntax for an expression statement is:

An expression statement evaluates the expression list (which may be a single expression).

In interactive mode, if the value is not None , it is converted to a string using the built-in repr() function and the resulting string is written to standard output on a line by itself (except if the result is None , so that procedure calls do not cause any output.)

7.2. Assignment statements ¶

Assignment statements are used to (re)bind names to values and to modify attributes or items of mutable objects:

(See section Primaries for the syntax definitions for attributeref , subscription , and slicing .)

An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right.

Assignment is defined recursively depending on the form of the target (list). When a target is part of a mutable object (an attribute reference, subscription or slicing), the mutable object must ultimately perform the assignment and decide about its validity, and may raise an exception if the assignment is unacceptable. The rules observed by various types and the exceptions raised are given with the definition of the object types (see section The standard type hierarchy ).

Assignment of an object to a target list, optionally enclosed in parentheses or square brackets, is recursively defined as follows.

If the target list is a single target with no trailing comma, optionally in parentheses, the object is assigned to that target.

If the target list contains one target prefixed with an asterisk, called a “starred” target: The object must be an iterable with at least as many items as there are targets in the target list, minus one. The first items of the iterable are assigned, from left to right, to the targets before the starred target. The final items of the iterable are assigned to the targets after the starred target. A list of the remaining items in the iterable is then assigned to the starred target (the list can be empty).

Else: The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets.

Assignment of an object to a single target is recursively defined as follows.

If the target is an identifier (name):

If the name does not occur in a global or nonlocal statement in the current code block: the name is bound to the object in the current local namespace.

Otherwise: the name is bound to the object in the global namespace or the outer namespace determined by nonlocal , respectively.

The name is rebound if it was already bound. This may cause the reference count for the object previously bound to the name to reach zero, causing the object to be deallocated and its destructor (if it has one) to be called.

If the target is an attribute reference: The primary expression in the reference is evaluated. It should yield an object with assignable attributes; if this is not the case, TypeError is raised. That object is then asked to assign the assigned object to the given attribute; if it cannot perform the assignment, it raises an exception (usually but not necessarily AttributeError ).

Note: If the object is a class instance and the attribute reference occurs on both sides of the assignment operator, the right-hand side expression, a.x can access either an instance attribute or (if no instance attribute exists) a class attribute. The left-hand side target a.x is always set as an instance attribute, creating it if necessary. Thus, the two occurrences of a.x do not necessarily refer to the same attribute: if the right-hand side expression refers to a class attribute, the left-hand side creates a new instance attribute as the target of the assignment:

This description does not necessarily apply to descriptor attributes, such as properties created with property() .

If the target is a subscription: The primary expression in the reference is evaluated. It should yield either a mutable sequence object (such as a list) or a mapping object (such as a dictionary). Next, the subscript expression is evaluated.

If the primary is a mutable sequence object (such as a list), the subscript must yield an integer. If it is negative, the sequence’s length is added to it. The resulting value must be a nonnegative integer less than the sequence’s length, and the sequence is asked to assign the assigned object to its item with that index. If the index is out of range, IndexError is raised (assignment to a subscripted sequence cannot add new items to a list).

If the primary is a mapping object (such as a dictionary), the subscript must have a type compatible with the mapping’s key type, and the mapping is then asked to create a key/value pair which maps the subscript to the assigned object. This can either replace an existing key/value pair with the same key value, or insert a new key/value pair (if no key with the same value existed).

For user-defined objects, the __setitem__() method is called with appropriate arguments.

If the target is a slicing: The primary expression in the reference is evaluated. It should yield a mutable sequence object (such as a list). The assigned object should be a sequence object of the same type. Next, the lower and upper bound expressions are evaluated, insofar they are present; defaults are zero and the sequence’s length. The bounds should evaluate to integers. If either bound is negative, the sequence’s length is added to it. The resulting bounds are clipped to lie between zero and the sequence’s length, inclusive. Finally, the sequence object is asked to replace the slice with the items of the assigned sequence. The length of the slice may be different from the length of the assigned sequence, thus changing the length of the target sequence, if the target sequence allows it.

CPython implementation detail: In the current implementation, the syntax for targets is taken to be the same as for expressions, and invalid syntax is rejected during the code generation phase, causing less detailed error messages.

Although the definition of assignment implies that overlaps between the left-hand side and the right-hand side are ‘simultaneous’ (for example a, b = b, a swaps two variables), overlaps within the collection of assigned-to variables occur left-to-right, sometimes resulting in confusion. For instance, the following program prints [0, 2] :

The specification for the *target feature.

7.2.1. Augmented assignment statements ¶

Augmented assignment is the combination, in a single statement, of a binary operation and an assignment statement:

(See section Primaries for the syntax definitions of the last three symbols.)

An augmented assignment evaluates the target (which, unlike normal assignment statements, cannot be an unpacking) and the expression list, performs the binary operation specific to the type of assignment on the two operands, and assigns the result to the original target. The target is only evaluated once.

An augmented assignment statement like x += 1 can be rewritten as x = x + 1 to achieve a similar, but not exactly equal effect. In the augmented version, x is only evaluated once. Also, when possible, the actual operation is performed in-place , meaning that rather than creating a new object and assigning that to the target, the old object is modified instead.

Unlike normal assignments, augmented assignments evaluate the left-hand side before evaluating the right-hand side. For example, a[i] += f(x) first looks-up a[i] , then it evaluates f(x) and performs the addition, and lastly, it writes the result back to a[i] .

With the exception of assigning to tuples and multiple targets in a single statement, the assignment done by augmented assignment statements is handled the same way as normal assignments. Similarly, with the exception of the possible in-place behavior, the binary operation performed by augmented assignment is the same as the normal binary operations.

For targets which are attribute references, the same caveat about class and instance attributes applies as for regular assignments.

7.2.2. Annotated assignment statements ¶

Annotation assignment is the combination, in a single statement, of a variable or attribute annotation and an optional assignment statement:

The difference from normal Assignment statements is that only a single target is allowed.

The assignment target is considered “simple” if it consists of a single name that is not enclosed in parentheses. For simple assignment targets, if in class or module scope, the annotations are evaluated and stored in a special class or module attribute __annotations__ that is a dictionary mapping from variable names (mangled if private) to evaluated annotations. This attribute is writable and is automatically created at the start of class or module body execution, if annotations are found statically.

If the assignment target is not simple (an attribute, subscript node, or parenthesized name), the annotation is evaluated if in class or module scope, but not stored.

If a name is annotated in a function scope, then this name is local for that scope. Annotations are never evaluated and stored in function scopes.

If the right hand side is present, an annotated assignment performs the actual assignment before evaluating annotations (where applicable). If the right hand side is not present for an expression target, then the interpreter evaluates the target except for the last __setitem__() or __setattr__() call.

The proposal that added syntax for annotating the types of variables (including class variables and instance variables), instead of expressing them through comments.

The proposal that added the typing module to provide a standard syntax for type annotations that can be used in static analysis tools and IDEs.

Changed in version 3.8: Now annotated assignments allow the same expressions in the right hand side as regular assignments. Previously, some expressions (like un-parenthesized tuple expressions) caused a syntax error.

7.3. The assert statement ¶

Assert statements are a convenient way to insert debugging assertions into a program:

The simple form, assert expression , is equivalent to

The extended form, assert expression1, expression2 , is equivalent to

These equivalences assume that __debug__ and AssertionError refer to the built-in variables with those names. In the current implementation, the built-in variable __debug__ is True under normal circumstances, False when optimization is requested (command line option -O ). The current code generator emits no code for an assert statement when optimization is requested at compile time. Note that it is unnecessary to include the source code for the expression that failed in the error message; it will be displayed as part of the stack trace.

Assignments to __debug__ are illegal. The value for the built-in variable is determined when the interpreter starts.

7.4. The pass statement ¶

pass is a null operation — when it is executed, nothing happens. It is useful as a placeholder when a statement is required syntactically, but no code needs to be executed, for example:

7.5. The del statement ¶

Deletion is recursively defined very similar to the way assignment is defined. Rather than spelling it out in full details, here are some hints.

Deletion of a target list recursively deletes each target, from left to right.

Deletion of a name removes the binding of that name from the local or global namespace, depending on whether the name occurs in a global statement in the same code block. If the name is unbound, a NameError exception will be raised.

Deletion of attribute references, subscriptions and slicings is passed to the primary object involved; deletion of a slicing is in general equivalent to assignment of an empty slice of the right type (but even this is determined by the sliced object).

Changed in version 3.2: Previously it was illegal to delete a name from the local namespace if it occurs as a free variable in a nested block.

7.6. The return statement ¶

return may only occur syntactically nested in a function definition, not within a nested class definition.

If an expression list is present, it is evaluated, else None is substituted.

return leaves the current function call with the expression list (or None ) as return value.

When return passes control out of a try statement with a finally clause, that finally clause is executed before really leaving the function.

In a generator function, the return statement indicates that the generator is done and will cause StopIteration to be raised. The returned value (if any) is used as an argument to construct StopIteration and becomes the StopIteration.value attribute.

In an asynchronous generator function, an empty return statement indicates that the asynchronous generator is done and will cause StopAsyncIteration to be raised. A non-empty return statement is a syntax error in an asynchronous generator function.

7.7. The yield statement ¶

A yield statement is semantically equivalent to a yield expression . The yield statement can be used to omit the parentheses that would otherwise be required in the equivalent yield expression statement. For example, the yield statements

are equivalent to the yield expression statements

Yield expressions and statements are only used when defining a generator function, and are only used in the body of the generator function. Using yield in a function definition is sufficient to cause that definition to create a generator function instead of a normal function.

For full details of yield semantics, refer to the Yield expressions section.

7.8. The raise statement ¶

If no expressions are present, raise re-raises the exception that is currently being handled, which is also known as the active exception . If there isn’t currently an active exception, a RuntimeError exception is raised indicating that this is an error.

Otherwise, raise evaluates the first expression as the exception object. It must be either a subclass or an instance of BaseException . If it is a class, the exception instance will be obtained when needed by instantiating the class with no arguments.

The type of the exception is the exception instance’s class, the value is the instance itself.

A traceback object is normally created automatically when an exception is raised and attached to it as the __traceback__ attribute. You can create an exception and set your own traceback in one step using the with_traceback() exception method (which returns the same exception instance, with its traceback set to its argument), like so:

The from clause is used for exception chaining: if given, the second expression must be another exception class or instance. If the second expression is an exception instance, it will be attached to the raised exception as the __cause__ attribute (which is writable). If the expression is an exception class, the class will be instantiated and the resulting exception instance will be attached to the raised exception as the __cause__ attribute. If the raised exception is not handled, both exceptions will be printed:

A similar mechanism works implicitly if a new exception is raised when an exception is already being handled. An exception may be handled when an except or finally clause, or a with statement, is used. The previous exception is then attached as the new exception’s __context__ attribute:

Exception chaining can be explicitly suppressed by specifying None in the from clause:

Additional information on exceptions can be found in section Exceptions , and information about handling exceptions is in section The try statement .

Changed in version 3.3: None is now permitted as Y in raise X from Y .

Added the __suppress_context__ attribute to suppress automatic display of the exception context.

Changed in version 3.11: If the traceback of the active exception is modified in an except clause, a subsequent raise statement re-raises the exception with the modified traceback. Previously, the exception was re-raised with the traceback it had when it was caught.

7.9. The break statement ¶

break may only occur syntactically nested in a for or while loop, but not nested in a function or class definition within that loop.

It terminates the nearest enclosing loop, skipping the optional else clause if the loop has one.

If a for loop is terminated by break , the loop control target keeps its current value.

When break passes control out of a try statement with a finally clause, that finally clause is executed before really leaving the loop.

7.10. The continue statement ¶

continue may only occur syntactically nested in a for or while loop, but not nested in a function or class definition within that loop. It continues with the next cycle of the nearest enclosing loop.

When continue passes control out of a try statement with a finally clause, that finally clause is executed before really starting the next loop cycle.

7.11. The import statement ¶

The basic import statement (no from clause) is executed in two steps:

find a module, loading and initializing it if necessary

define a name or names in the local namespace for the scope where the import statement occurs.

When the statement contains multiple clauses (separated by commas) the two steps are carried out separately for each clause, just as though the clauses had been separated out into individual import statements.

The details of the first step, finding and loading modules, are described in greater detail in the section on the import system , which also describes the various types of packages and modules that can be imported, as well as all the hooks that can be used to customize the import system. Note that failures in this step may indicate either that the module could not be located, or that an error occurred while initializing the module, which includes execution of the module’s code.

If the requested module is retrieved successfully, it will be made available in the local namespace in one of three ways:

If the module name is followed by as , then the name following as is bound directly to the imported module.

If no other name is specified, and the module being imported is a top level module, the module’s name is bound in the local namespace as a reference to the imported module

If the module being imported is not a top level module, then the name of the top level package that contains the module is bound in the local namespace as a reference to the top level package. The imported module must be accessed using its full qualified name rather than directly

The from form uses a slightly more complex process:

find the module specified in the from clause, loading and initializing it if necessary;

for each of the identifiers specified in the import clauses:

check if the imported module has an attribute by that name

if not, attempt to import a submodule with that name and then check the imported module again for that attribute

if the attribute is not found, ImportError is raised.

otherwise, a reference to that value is stored in the local namespace, using the name in the as clause if it is present, otherwise using the attribute name

If the list of identifiers is replaced by a star ( '*' ), all public names defined in the module are bound in the local namespace for the scope where the import statement occurs.

The public names defined by a module are determined by checking the module’s namespace for a variable named __all__ ; if defined, it must be a sequence of strings which are names defined or imported by that module. The names given in __all__ are all considered public and are required to exist. If __all__ is not defined, the set of public names includes all names found in the module’s namespace which do not begin with an underscore character ( '_' ). __all__ should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).

The wild card form of import — from module import * — is only allowed at the module level. Attempting to use it in class or function definitions will raise a SyntaxError .

When specifying what module to import you do not have to specify the absolute name of the module. When a module or package is contained within another package it is possible to make a relative import within the same top package without having to mention the package name. By using leading dots in the specified module or package after from you can specify how high to traverse up the current package hierarchy without specifying exact names. One leading dot means the current package where the module making the import exists. Two dots means up one package level. Three dots is up two levels, etc. So if you execute from . import mod from a module in the pkg package then you will end up importing pkg.mod . If you execute from ..subpkg2 import mod from within pkg.subpkg1 you will import pkg.subpkg2.mod . The specification for relative imports is contained in the Package Relative Imports section.

importlib.import_module() is provided to support applications that determine dynamically the modules to be loaded.

Raises an auditing event import with arguments module , filename , sys.path , sys.meta_path , sys.path_hooks .

7.11.1. Future statements ¶

A future statement is a directive to the compiler that a particular module should be compiled using syntax or semantics that will be available in a specified future release of Python where the feature becomes standard.

The future statement is intended to ease migration to future versions of Python that introduce incompatible changes to the language. It allows use of the new features on a per-module basis before the release in which the feature becomes standard.

A future statement must appear near the top of the module. The only lines that can appear before a future statement are:

the module docstring (if any),

blank lines, and

other future statements.

The only feature that requires using the future statement is annotations (see PEP 563 ).

All historical features enabled by the future statement are still recognized by Python 3. The list includes absolute_import , division , generators , generator_stop , unicode_literals , print_function , nested_scopes and with_statement . They are all redundant because they are always enabled, and only kept for backwards compatibility.

A future statement is recognized and treated specially at compile time: Changes to the semantics of core constructs are often implemented by generating different code. It may even be the case that a new feature introduces new incompatible syntax (such as a new reserved word), in which case the compiler may need to parse the module differently. Such decisions cannot be pushed off until runtime.

For any given release, the compiler knows which feature names have been defined, and raises a compile-time error if a future statement contains a feature not known to it.

The direct runtime semantics are the same as for any import statement: there is a standard module __future__ , described later, and it will be imported in the usual way at the time the future statement is executed.

The interesting runtime semantics depend on the specific feature enabled by the future statement.

Note that there is nothing special about the statement:

That is not a future statement; it’s an ordinary import statement with no special semantics or syntax restrictions.

Code compiled by calls to the built-in functions exec() and compile() that occur in a module M containing a future statement will, by default, use the new syntax or semantics associated with the future statement. This can be controlled by optional arguments to compile() — see the documentation of that function for details.

A future statement typed at an interactive interpreter prompt will take effect for the rest of the interpreter session. If an interpreter is started with the -i option, is passed a script name to execute, and the script includes a future statement, it will be in effect in the interactive session started after the script is executed.

The original proposal for the __future__ mechanism.

7.12. The global statement ¶

The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals. It would be impossible to assign to a global variable without global , although free variables may refer to globals without being declared global.

Names listed in a global statement must not be used in the same code block textually preceding that global statement.

Names listed in a global statement must not be defined as formal parameters, or as targets in with statements or except clauses, or in a for target list, class definition, function definition, import statement, or variable annotation.

CPython implementation detail: The current implementation does not enforce some of these restrictions, but programs should not abuse this freedom, as future implementations may enforce them or silently change the meaning of the program.

Programmer’s note: global is a directive to the parser. It applies only to code parsed at the same time as the global statement. In particular, a global statement contained in a string or code object supplied to the built-in exec() function does not affect the code block containing the function call, and code contained in such a string is unaffected by global statements in the code containing the function call. The same applies to the eval() and compile() functions.

7.13. The nonlocal statement ¶

When the definition of a function or class is nested (enclosed) within the definitions of other functions, its nonlocal scopes are the local scopes of the enclosing functions. The nonlocal statement causes the listed identifiers to refer to names previously bound in nonlocal scopes. It allows encapsulated code to rebind such nonlocal identifiers. If a name is bound in more than one nonlocal scope, the nearest binding is used. If a name is not bound in any nonlocal scope, or if there is no nonlocal scope, a SyntaxError is raised.

The nonlocal statement applies to the entire scope of a function or class body. A SyntaxError is raised if a variable is used or assigned to prior to its nonlocal declaration in the scope.

The specification for the nonlocal statement.

Programmer’s note: nonlocal is a directive to the parser and applies only to code parsed along with it. See the note for the global statement.

7.14. The type statement ¶

The type statement declares a type alias, which is an instance of typing.TypeAliasType .

For example, the following statement creates a type alias:

This code is roughly equivalent to:

annotation-def indicates an annotation scope , which behaves mostly like a function, but with several small differences.

The value of the type alias is evaluated in the annotation scope. It is not evaluated when the type alias is created, but only when the value is accessed through the type alias’s __value__ attribute (see Lazy evaluation ). This allows the type alias to refer to names that are not yet defined.

Type aliases may be made generic by adding a type parameter list after the name. See Generic type aliases for more.

type is a soft keyword .

Added in version 3.12.

Introduced the type statement and syntax for generic classes and functions.

Table of Contents

  • 7.1. Expression statements
  • 7.2.1. Augmented assignment statements
  • 7.2.2. Annotated assignment statements
  • 7.3. The assert statement
  • 7.4. The pass statement
  • 7.5. The del statement
  • 7.6. The return statement
  • 7.7. The yield statement
  • 7.8. The raise statement
  • 7.9. The break statement
  • 7.10. The continue statement
  • 7.11.1. Future statements
  • 7.12. The global statement
  • 7.13. The nonlocal statement
  • 7.14. The type statement

Previous topic

6. Expressions

8. Compound statements

  • Report a Bug
  • Show Source
  • Hands-on Python Tutorial »
  • 3. More On Flow of Control »

3.1. If Statements ¶

3.1.1. simple conditions ¶.

The statements introduced in this chapter will involve tests or conditions . More syntax for conditions will be introduced later, but for now consider simple arithmetic comparisons that directly translate from math into Python. Try each line separately in the Shell

You see that conditions are either True or False . These are the only possible Boolean values (named after 19th century mathematician George Boole). In Python the name Boolean is shortened to the type bool . It is the type of the results of true-false conditions or tests.

The Boolean values True and False have no quotes around them! Just as '123' is a string and 123 without the quotes is not, 'True' is a string, not of type bool.

3.1.2. Simple if Statements ¶

Run this example program, suitcase.py. Try it at least twice, with inputs: 30 and then 55. As you an see, you get an extra result, depending on the input. The main code is:

The middle two line are an if statement. It reads pretty much like English. If it is true that the weight is greater than 50, then print the statement about an extra charge. If it is not true that the weight is greater than 50, then don’t do the indented part: skip printing the extra luggage charge. In any event, when you have finished with the if statement (whether it actually does anything or not), go on to the next statement that is not indented under the if . In this case that is the statement printing “Thank you”.

The general Python syntax for a simple if statement is

if condition : indentedStatementBlock

If the condition is true, then do the indented statements. If the condition is not true, then skip the indented statements.

Another fragment as an example:

As with other kinds of statements with a heading and an indented block, the block can have more than one statement. The assumption in the example above is that if an account goes negative, it is brought back to 0 by transferring money from a backup account in several steps.

In the examples above the choice is between doing something (if the condition is True ) or nothing (if the condition is False ). Often there is a choice of two possibilities, only one of which will be done, depending on the truth of a condition.

3.1.3. if - else Statements ¶

Run the example program, clothes.py . Try it at least twice, with inputs 50 and then 80. As you can see, you get different results, depending on the input. The main code of clothes.py is:

The middle four lines are an if-else statement. Again it is close to English, though you might say “otherwise” instead of “else” (but else is shorter!). There are two indented blocks: One, like in the simple if statement, comes right after the if heading and is executed when the condition in the if heading is true. In the if - else form this is followed by an else: line, followed by another indented block that is only executed when the original condition is false . In an if - else statement exactly one of two possible indented blocks is executed.

A line is also shown de dented next, removing indentation, about getting exercise. Since it is dedented, it is not a part of the if-else statement: Since its amount of indentation matches the if heading, it is always executed in the normal forward flow of statements, after the if - else statement (whichever block is selected).

The general Python if - else syntax is

if condition : indentedStatementBlockForTrueCondition else: indentedStatementBlockForFalseCondition

These statement blocks can have any number of statements, and can include about any kind of statement.

See Graduate Exercise

3.1.4. More Conditional Expressions ¶

All the usual arithmetic comparisons may be made, but many do not use standard mathematical symbolism, mostly for lack of proper keys on a standard keyboard.

Meaning Math Symbol Python Symbols
Less than <
Greater than >
Less than or equal
Greater than or equal
Equals =
Not equal

There should not be space between the two-symbol Python substitutes.

Notice that the obvious choice for equals , a single equal sign, is not used to check for equality. An annoying second equal sign is required. This is because the single equal sign is already used for assignment in Python, so it is not available for tests.

It is a common error to use only one equal sign when you mean to test for equality, and not make an assignment!

Tests for equality do not make an assignment, and they do not require a variable on the left. Any expressions can be tested for equality or inequality ( != ). They do not need to be numbers! Predict the results and try each line in the Shell :

An equality check does not make an assignment. Strings are case sensitive. Order matters in a list.

Try in the Shell :

When the comparison does not make sense, an Exception is caused. [1]

Following up on the discussion of the inexactness of float arithmetic in String Formats for Float Precision , confirm that Python does not consider .1 + .2 to be equal to .3: Write a simple condition into the Shell to test.

Here is another example: Pay with Overtime. Given a person’s work hours for the week and regular hourly wage, calculate the total pay for the week, taking into account overtime. Hours worked over 40 are overtime, paid at 1.5 times the normal rate. This is a natural place for a function enclosing the calculation.

Read the setup for the function:

The problem clearly indicates two cases: when no more than 40 hours are worked or when more than 40 hours are worked. In case more than 40 hours are worked, it is convenient to introduce a variable overtimeHours. You are encouraged to think about a solution before going on and examining mine.

You can try running my complete example program, wages.py, also shown below. The format operation at the end of the main function uses the floating point format ( String Formats for Float Precision ) to show two decimal places for the cents in the answer:

Here the input was intended to be numeric, but it could be decimal so the conversion from string was via float , not int .

Below is an equivalent alternative version of the body of calcWeeklyWages , used in wages1.py . It uses just one general calculation formula and sets the parameters for the formula in the if statement. There are generally a number of ways you might solve the same problem!

There are also Boolean operators that are applied to types others than numbers. A useful Boolean operator is in , checking membership in a sequence:

It can also be used with not , as not in , to mean the opposite:

In general the two versions are:

item in sequence item not in sequence

Detecting the need for if statements : Like with planning programs needing``for`` statements, you want to be able to translate English descriptions of problems that would naturally include if or if - else statements. What are some words or phrases or ideas that suggest the use of these statements? Think of your own and then compare to a few I gave: [2]

3.1.4.1. Graduate Exercise ¶

Write a program, graduate.py , that prompts students for how many credits they have. Print whether of not they have enough credits for graduation. (At Loyola University Chicago 120 credits are needed for graduation.)

3.1.4.2. Head or Tails Exercise ¶

Write a program headstails.py . It should include a function flip() , that simulates a single flip of a coin: It randomly prints either Heads or Tails . Accomplish this by choosing 0 or 1 arbitrarily with random.randrange(2) , and use an if - else statement to print Heads when the result is 0, and Tails otherwise.

In your main program have a simple repeat loop that calls flip() 10 times to test it, so you generate a random sequence of 10 Heads and Tails .

3.1.4.3. Strange Function Exercise ¶

Save the example program jumpFuncStub.py as jumpFunc.py , and complete the definitions of functions jump and main as described in the function documentation strings in the program. In the jump function definition use an if - else statement (hint [3] ). In the main function definition use a for -each loop, the range function, and the jump function.

The jump function is introduced for use in Strange Sequence Exercise , and others after that.

3.1.5. Multiple Tests and if - elif Statements ¶

Often you want to distinguish between more than two distinct cases, but conditions only have two possible results, True or False , so the only direct choice is between two options. As anyone who has played “20 Questions” knows, you can distinguish more cases by further questions. If there are more than two choices, a single test may only reduce the possibilities, but further tests can reduce the possibilities further and further. Since most any kind of statement can be placed in an indented statement block, one choice is a further if statement. For instance consider a function to convert a numerical grade to a letter grade, ‘A’, ‘B’, ‘C’, ‘D’ or ‘F’, where the cutoffs for ‘A’, ‘B’, ‘C’, and ‘D’ are 90, 80, 70, and 60 respectively. One way to write the function would be test for one grade at a time, and resolve all the remaining possibilities inside the next else clause:

This repeatedly increasing indentation with an if statement as the else block can be annoying and distracting. A preferred alternative in this situation, that avoids all this indentation, is to combine each else and if block into an elif block:

The most elaborate syntax for an if - elif - else statement is indicated in general below:

if condition1 : indentedStatementBlockForTrueCondition1 elif condition2 : indentedStatementBlockForFirstTrueCondition2 elif condition3 : indentedStatementBlockForFirstTrueCondition3 elif condition4 : indentedStatementBlockForFirstTrueCondition4 else: indentedStatementBlockForEachConditionFalse

The if , each elif , and the final else lines are all aligned. There can be any number of elif lines, each followed by an indented block. (Three happen to be illustrated above.) With this construction exactly one of the indented blocks is executed. It is the one corresponding to the first True condition, or, if all conditions are False , it is the block after the final else line.

Be careful of the strange Python contraction. It is elif , not elseif . A program testing the letterGrade function is in example program grade1.py .

See Grade Exercise .

A final alternative for if statements: if - elif -.... with no else . This would mean changing the syntax for if - elif - else above so the final else: and the block after it would be omitted. It is similar to the basic if statement without an else , in that it is possible for no indented block to be executed. This happens if none of the conditions in the tests are true.

With an else included, exactly one of the indented blocks is executed. Without an else , at most one of the indented blocks is executed.

This if - elif statement only prints a line if there is a problem with the weight of the suitcase.

3.1.5.1. Sign Exercise ¶

Write a program sign.py to ask the user for a number. Print out which category the number is in: 'positive' , 'negative' , or 'zero' .

3.1.5.2. Grade Exercise ¶

In Idle, load grade1.py and save it as grade2.py Modify grade2.py so it has an equivalent version of the letterGrade function that tests in the opposite order, first for F, then D, C, .... Hint: How many tests do you need to do? [4]

Be sure to run your new version and test with different inputs that test all the different paths through the program. Be careful to test around cut-off points. What does a grade of 79.6 imply? What about exactly 80?

3.1.5.3. Wages Exercise ¶

* Modify the wages.py or the wages1.py example to create a program wages2.py that assumes people are paid double time for hours over 60. Hence they get paid for at most 20 hours overtime at 1.5 times the normal rate. For example, a person working 65 hours with a regular wage of $10 per hour would work at $10 per hour for 40 hours, at 1.5 * $10 for 20 hours of overtime, and 2 * $10 for 5 hours of double time, for a total of

10*40 + 1.5*10*20 + 2*10*5 = $800.

You may find wages1.py easier to adapt than wages.py .

Be sure to test all paths through the program! Your program is likely to be a modification of a program where some choices worked before, but once you change things, retest for all the cases! Changes can mess up things that worked before.

3.1.6. Nesting Control-Flow Statements ¶

The power of a language like Python comes largely from the variety of ways basic statements can be combined . In particular, for and if statements can be nested inside each other’s indented blocks. For example, suppose you want to print only the positive

numbers from an arbitrary list of numbers in a function with the following heading. Read the pieces for now.

For example, suppose numberList is [3, -5, 2, -1, 0, 7] . You want to process a list, so that suggests a for -each loop,

but a for -each loop runs the same code body for each element of the list, and we only want

for some of them. That seems like a major obstacle, but think closer at what needs to happen concretely. As a human, who has eyes of amazing capacity, you are drawn immediately to the actual correct numbers, 3, 2, and 7, but clearly a computer doing this systematically will have to check every number. In fact, there is a consistent action required: Every number must be tested to see if it should be printed. This suggests an if statement, with the condition num > 0 . Try loading into Idle and running the example program onlyPositive.py , whose code is shown below. It ends with a line testing the function:

This idea of nesting if statements enormously expands the possibilities with loops. Now different things can be done at different times in loops, as long as there is a consistent test to allow a choice between the alternatives. Shortly, while loops will also be introduced, and you will see if statements nested inside of them, too.

The rest of this section deals with graphical examples.

Run example program bounce1.py . It has a red ball moving and bouncing obliquely off the edges. If you watch several times, you should see that it starts from random locations. Also you can repeat the program from the Shell prompt after you have run the script. For instance, right after running the program, try in the Shell

The parameters give the amount the shape moves in each animation step. You can try other values in the Shell , preferably with magnitudes less than 10.

For the remainder of the description of this example, read the extracted text pieces.

The animations before this were totally scripted, saying exactly how many moves in which direction, but in this case the direction of motion changes with every bounce. The program has a graphic object shape and the central animation step is

but in this case, dx and dy have to change when the ball gets to a boundary. For instance, imagine the ball getting to the left side as it is moving to the left and up. The bounce obviously alters the horizontal part of the motion, in fact reversing it, but the ball would still continue up. The reversal of the horizontal part of the motion means that the horizontal shift changes direction and therefore its sign:

but dy does not need to change. This switch does not happen at each animation step, but only when the ball reaches the edge of the window. It happens only some of the time - suggesting an if statement. Still the condition must be determined. Suppose the center of the ball has coordinates (x, y). When x reaches some particular x coordinate, call it xLow, the ball should bounce.

The edge of the window is at coordinate 0, but xLow should not be 0, or the ball would be half way off the screen before bouncing! For the edge of the ball to hit the edge of the screen, the x coordinate of the center must be the length of the radius away, so actually xLow is the radius of the ball.

Animation goes quickly in small steps, so I cheat. I allow the ball to take one (small, quick) step past where it really should go ( xLow ), and then we reverse it so it comes back to where it belongs. In particular

There are similar bounding variables xHigh , yLow and yHigh , all the radius away from the actual edge coordinates, and similar conditions to test for a bounce off each possible edge. Note that whichever edge is hit, one coordinate, either dx or dy, reverses. One way the collection of tests could be written is

This approach would cause there to be some extra testing: If it is true that x < xLow , then it is impossible for it to be true that x > xHigh , so we do not need both tests together. We avoid unnecessary tests with an elif clause (for both x and y):

Note that the middle if is not changed to an elif , because it is possible for the ball to reach a corner , and need both dx and dy reversed.

The program also uses several methods to read part of the state of graphics objects that we have not used in examples yet. Various graphics objects, like the circle we are using as the shape, know their center point, and it can be accessed with the getCenter() method. (Actually a clone of the point is returned.) Also each coordinate of a Point can be accessed with the getX() and getY() methods.

This explains the new features in the central function defined for bouncing around in a box, bounceInBox . The animation arbitrarily goes on in a simple repeat loop for 600 steps. (A later example will improve this behavior.)

The program starts the ball from an arbitrary point inside the allowable rectangular bounds. This is encapsulated in a utility function included in the program, getRandomPoint . The getRandomPoint function uses the randrange function from the module random . Note that in parameters for both the functions range and randrange , the end stated is past the last value actually desired:

The full program is listed below, repeating bounceInBox and getRandomPoint for completeness. Several parts that may be useful later, or are easiest to follow as a unit, are separated out as functions. Make sure you see how it all hangs together or ask questions!

3.1.6.1. Short String Exercise ¶

Write a program short.py with a function printShort with heading:

In your main program, test the function, calling it several times with different lists of strings. Hint: Find the length of each string with the len function.

The function documentation here models a common approach: illustrating the behavior of the function with a Python Shell interaction. This part begins with a line starting with >>> . Other exercises and examples will also document behavior in the Shell.

3.1.6.2. Even Print Exercise ¶

Write a program even1.py with a function printEven with heading:

In your main program, test the function, calling it several times with different lists of integers. Hint: A number is even if its remainder, when dividing by 2, is 0.

3.1.6.3. Even List Exercise ¶

Write a program even2.py with a function chooseEven with heading:

In your main program, test the function, calling it several times with different lists of integers and printing the results in the main program. (The documentation string illustrates the function call in the Python shell, where the return value is automatically printed. Remember, that in a program, you only print what you explicitly say to print.) Hint: In the function, create a new list, and append the appropriate numbers to it, before returning the result.

3.1.6.4. Unique List Exercise ¶

* The madlib2.py program has its getKeys function, which first generates a list of each occurrence of a cue in the story format. This gives the cues in order, but likely includes repetitions. The original version of getKeys uses a quick method to remove duplicates, forming a set from the list. There is a disadvantage in the conversion, though: Sets are not ordered, so when you iterate through the resulting set, the order of the cues will likely bear no resemblance to the order they first appeared in the list. That issue motivates this problem:

Copy madlib2.py to madlib2a.py , and add a function with this heading:

Hint: Process aList in order. Use the in syntax to only append elements to a new list that are not already in the new list.

After perfecting the uniqueList function, replace the last line of getKeys , so it uses uniqueList to remove duplicates in keyList .

Check that your madlib2a.py prompts you for cue values in the order that the cues first appear in the madlib format string.

3.1.7. Compound Boolean Expressions ¶

To be eligible to graduate from Loyola University Chicago, you must have 120 credits and a GPA of at least 2.0. This translates directly into Python as a compound condition :

This is true if both credits >= 120 is true and GPA >= 2.0 is true. A short example program using this would be:

The new Python syntax is for the operator and :

condition1 and condition2

The compound condition is true if both of the component conditions are true. It is false if at least one of the conditions is false.

See Congress Exercise .

In the last example in the previous section, there was an if - elif statement where both tests had the same block to be done if the condition was true:

There is a simpler way to state this in a sentence: If x < xLow or x > xHigh, switch the sign of dx. That translates directly into Python:

The word or makes another compound condition:

condition1 or condition2

is true if at least one of the conditions is true. It is false if both conditions are false. This corresponds to one way the word “or” is used in English. Other times in English “or” is used to mean exactly one alternative is true.

When translating a problem stated in English using “or”, be careful to determine whether the meaning matches Python’s or .

It is often convenient to encapsulate complicated tests inside a function. Think how to complete the function starting:

Recall that a Rectangle is specified in its constructor by two diagonally oppose Point s. This example gives the first use in the tutorials of the Rectangle methods that recover those two corner points, getP1 and getP2 . The program calls the points obtained this way pt1 and pt2 . The x and y coordinates of pt1 , pt2 , and point can be recovered with the methods of the Point type, getX() and getY() .

Suppose that I introduce variables for the x coordinates of pt1 , point , and pt2 , calling these x-coordinates end1 , val , and end2 , respectively. On first try you might decide that the needed mathematical relationship to test is

Unfortunately, this is not enough: The only requirement for the two corner points is that they be diagonally opposite, not that the coordinates of the second point are higher than the corresponding coordinates of the first point. It could be that end1 is 200; end2 is 100, and val is 120. In this latter case val is between end1 and end2 , but substituting into the expression above

is False. The 100 and 200 need to be reversed in this case. This makes a complicated situation. Also this is an issue which must be revisited for both the x and y coordinates. I introduce an auxiliary function isBetween to deal with one coordinate at a time. It starts:

Clearly this is true if the original expression, end1 <= val <= end2 , is true. You must also consider the possible case when the order of the ends is reversed: end2 <= val <= end1 . How do we combine these two possibilities? The Boolean connectives to consider are and and or . Which applies? You only need one to be true, so or is the proper connective:

A correct but redundant function body would be:

Check the meaning: if the compound expression is True , return True . If the condition is False , return False – in either case return the same value as the test condition. See that a much simpler and neater version is to just return the value of the condition itself!

In general you should not need an if - else statement to choose between true and false values! Operate directly on the boolean expression.

A side comment on expressions like

Other than the two-character operators, this is like standard math syntax, chaining comparisons. In Python any number of comparisons can be chained in this way, closely approximating mathematical notation. Though this is good Python, be aware that if you try other high-level languages like Java and C++, such an expression is gibberish. Another way the expression can be expressed (and which translates directly to other languages) is:

So much for the auxiliary function isBetween . Back to the isInside function. You can use the isBetween function to check the x coordinates,

and to check the y coordinates,

Again the question arises: how do you combine the two tests?

In this case we need the point to be both between the sides and between the top and bottom, so the proper connector is and .

Think how to finish the isInside method. Hint: [5]

Sometimes you want to test the opposite of a condition. As in English you can use the word not . For instance, to test if a Point was not inside Rectangle Rect, you could use the condition

In general,

not condition

is True when condition is False , and False when condition is True .

The example program chooseButton1.py , shown below, is a complete program using the isInside function in a simple application, choosing colors. Pardon the length. Do check it out. It will be the starting point for a number of improvements that shorten it and make it more powerful in the next section. First a brief overview:

The program includes the functions isBetween and isInside that have already been discussed. The program creates a number of colored rectangles to use as buttons and also as picture components. Aside from specific data values, the code to create each rectangle is the same, so the action is encapsulated in a function, makeColoredRect . All of this is fine, and will be preserved in later versions.

The present main function is long, though. It has the usual graphics starting code, draws buttons and picture elements, and then has a number of code sections prompting the user to choose a color for a picture element. Each code section has a long if - elif - else test to see which button was clicked, and sets the color of the picture element appropriately.

The only further new feature used is in the long return statement in isInside .

Recall that Python is smart enough to realize that a statement continues to the next line if there is an unmatched pair of parentheses or brackets. Above is another situation with a long statement, but there are no unmatched parentheses on a line. For readability it is best not to make an enormous long line that would run off your screen or paper. Continuing to the next line is recommended. You can make the final character on a line be a backslash ( '\\' ) to indicate the statement continues on the next line. This is not particularly neat, but it is a rather rare situation. Most statements fit neatly on one line, and the creator of Python decided it was best to make the syntax simple in the most common situation. (Many other languages require a special statement terminator symbol like ‘;’ and pay no attention to newlines). Extra parentheses here would not hurt, so an alternative would be

The chooseButton1.py program is long partly because of repeated code. The next section gives another version involving lists.

3.1.7.1. Congress Exercise ¶

A person is eligible to be a US Senator who is at least 30 years old and has been a US citizen for at least 9 years. Write an initial version of a program congress.py to obtain age and length of citizenship from the user and print out if a person is eligible to be a Senator or not.

A person is eligible to be a US Representative who is at least 25 years old and has been a US citizen for at least 7 years. Elaborate your program congress.py so it obtains age and length of citizenship and prints out just the one of the following three statements that is accurate:

  • You are eligible for both the House and Senate.
  • You eligible only for the House.
  • You are ineligible for Congress.

3.1.8. More String Methods ¶

Here are a few more string methods useful in the next exercises, assuming the methods are applied to a string s :

s .startswith( pre )

returns True if string s starts with string pre : Both '-123'.startswith('-') and 'downstairs'.startswith('down') are True , but '1 - 2 - 3'.startswith('-') is False .

s .endswith( suffix )

returns True if string s ends with string suffix : Both 'whoever'.endswith('ever') and 'downstairs'.endswith('airs') are True , but '1 - 2 - 3'.endswith('-') is False .

s .replace( sub , replacement , count )

returns a new string with up to the first count occurrences of string sub replaced by replacement . The replacement can be the empty string to delete sub . For example:

3.1.8.1. Article Start Exercise ¶

In library alphabetizing, if the initial word is an article (“The”, “A”, “An”), then it is ignored when ordering entries. Write a program completing this function, and then testing it:

Be careful, if the title starts with “There”, it does not start with an article. What should you be testing for?

3.1.8.2. Is Number String Exercise ¶

** In the later Safe Number Input Exercise , it will be important to know if a string can be converted to the desired type of number. Explore that here. Save example isNumberStringStub.py as isNumberString.py and complete it. It contains headings and documentation strings for the functions in both parts of this exercise.

A legal whole number string consists entirely of digits. Luckily strings have an isdigit method, which is true when a nonempty string consists entirely of digits, so '2397'.isdigit() returns True , and '23a'.isdigit() returns False , exactly corresponding to the situations when the string represents a whole number!

In both parts be sure to test carefully. Not only confirm that all appropriate strings return True . Also be sure to test that you return False for all sorts of bad strings.

Recognizing an integer string is more involved, since it can start with a minus sign (or not). Hence the isdigit method is not enough by itself. This part is the most straightforward if you have worked on the sections String Indices and String Slices . An alternate approach works if you use the count method from Object Orientation , and some methods from this section.

Complete the function isIntStr .

Complete the function isDecimalStr , which introduces the possibility of a decimal point (though a decimal point is not required). The string methods mentioned in the previous part remain useful.

This is an improvement that is new in Python 3.
“In this case do ___; otherwise”, “if ___, then”, “when ___ is true, then”, “___ depends on whether”,
If you divide an even number by 2, what is the remainder? Use this idea in your condition.
4 tests to distinguish the 5 cases, as in the previous version
Once again, you are calculating and returning a Boolean result. You do not need an - statement.

Table Of Contents

  • 3.1.1. Simple Conditions
  • 3.1.2. Simple if Statements
  • 3.1.3. if - else Statements
  • 3.1.4.1. Graduate Exercise
  • 3.1.4.2. Head or Tails Exercise
  • 3.1.4.3. Strange Function Exercise
  • 3.1.5.1. Sign Exercise
  • 3.1.5.2. Grade Exercise
  • 3.1.5.3. Wages Exercise
  • 3.1.6.1. Short String Exercise
  • 3.1.6.2. Even Print Exercise
  • 3.1.6.3. Even List Exercise
  • 3.1.6.4. Unique List Exercise
  • 3.1.7.1. Congress Exercise
  • 3.1.8.1. Article Start Exercise
  • 3.1.8.2. Is Number String Exercise

Previous topic

3. More On Flow of Control

3.2. Loops and Tuples

  • Show Source

Quick search

Enter search terms or a module, class or function name.

Python Enhancement Proposals

  • Python »
  • PEP Index »

PEP 572 – Assignment Expressions

The importance of real code, exceptional cases, scope of the target, relative precedence of :=, change to evaluation order, differences between assignment expressions and assignment statements, specification changes during implementation, _pydecimal.py, datetime.py, sysconfig.py, simplifying list comprehensions, capturing condition values, changing the scope rules for comprehensions, alternative spellings, special-casing conditional statements, special-casing comprehensions, lowering operator precedence, allowing commas to the right, always requiring parentheses, why not just turn existing assignment into an expression, with assignment expressions, why bother with assignment statements, why not use a sublocal scope and prevent namespace pollution, style guide recommendations, acknowledgements, a numeric example, appendix b: rough code translations for comprehensions, appendix c: no changes to scope semantics.

This is a proposal for creating a way to assign to variables within an expression using the notation NAME := expr .

As part of this change, there is also an update to dictionary comprehension evaluation order to ensure key expressions are executed before value expressions (allowing the key to be bound to a name and then re-used as part of calculating the corresponding value).

During discussion of this PEP, the operator became informally known as “the walrus operator”. The construct’s formal name is “Assignment Expressions” (as per the PEP title), but they may also be referred to as “Named Expressions” (e.g. the CPython reference implementation uses that name internally).

Naming the result of an expression is an important part of programming, allowing a descriptive name to be used in place of a longer expression, and permitting reuse. Currently, this feature is available only in statement form, making it unavailable in list comprehensions and other expression contexts.

Additionally, naming sub-parts of a large expression can assist an interactive debugger, providing useful display hooks and partial results. Without a way to capture sub-expressions inline, this would require refactoring of the original code; with assignment expressions, this merely requires the insertion of a few name := markers. Removing the need to refactor reduces the likelihood that the code be inadvertently changed as part of debugging (a common cause of Heisenbugs), and is easier to dictate to another programmer.

During the development of this PEP many people (supporters and critics both) have had a tendency to focus on toy examples on the one hand, and on overly complex examples on the other.

The danger of toy examples is twofold: they are often too abstract to make anyone go “ooh, that’s compelling”, and they are easily refuted with “I would never write it that way anyway”.

The danger of overly complex examples is that they provide a convenient strawman for critics of the proposal to shoot down (“that’s obfuscated”).

Yet there is some use for both extremely simple and extremely complex examples: they are helpful to clarify the intended semantics. Therefore, there will be some of each below.

However, in order to be compelling , examples should be rooted in real code, i.e. code that was written without any thought of this PEP, as part of a useful application, however large or small. Tim Peters has been extremely helpful by going over his own personal code repository and picking examples of code he had written that (in his view) would have been clearer if rewritten with (sparing) use of assignment expressions. His conclusion: the current proposal would have allowed a modest but clear improvement in quite a few bits of code.

Another use of real code is to observe indirectly how much value programmers place on compactness. Guido van Rossum searched through a Dropbox code base and discovered some evidence that programmers value writing fewer lines over shorter lines.

Case in point: Guido found several examples where a programmer repeated a subexpression, slowing down the program, in order to save one line of code, e.g. instead of writing:

they would write:

Another example illustrates that programmers sometimes do more work to save an extra level of indentation:

This code tries to match pattern2 even if pattern1 has a match (in which case the match on pattern2 is never used). The more efficient rewrite would have been:

Syntax and semantics

In most contexts where arbitrary Python expressions can be used, a named expression can appear. This is of the form NAME := expr where expr is any valid Python expression other than an unparenthesized tuple, and NAME is an identifier.

The value of such a named expression is the same as the incorporated expression, with the additional side-effect that the target is assigned that value:

There are a few places where assignment expressions are not allowed, in order to avoid ambiguities or user confusion:

This rule is included to simplify the choice for the user between an assignment statement and an assignment expression – there is no syntactic position where both are valid.

Again, this rule is included to avoid two visually similar ways of saying the same thing.

This rule is included to disallow excessively confusing code, and because parsing keyword arguments is complex enough already.

This rule is included to discourage side effects in a position whose exact semantics are already confusing to many users (cf. the common style recommendation against mutable default values), and also to echo the similar prohibition in calls (the previous bullet).

The reasoning here is similar to the two previous cases; this ungrouped assortment of symbols and operators composed of : and = is hard to read correctly.

This allows lambda to always bind less tightly than := ; having a name binding at the top level inside a lambda function is unlikely to be of value, as there is no way to make use of it. In cases where the name will be used more than once, the expression is likely to need parenthesizing anyway, so this prohibition will rarely affect code.

This shows that what looks like an assignment operator in an f-string is not always an assignment operator. The f-string parser uses : to indicate formatting options. To preserve backwards compatibility, assignment operator usage inside of f-strings must be parenthesized. As noted above, this usage of the assignment operator is not recommended.

An assignment expression does not introduce a new scope. In most cases the scope in which the target will be bound is self-explanatory: it is the current scope. If this scope contains a nonlocal or global declaration for the target, the assignment expression honors that. A lambda (being an explicit, if anonymous, function definition) counts as a scope for this purpose.

There is one special case: an assignment expression occurring in a list, set or dict comprehension or in a generator expression (below collectively referred to as “comprehensions”) binds the target in the containing scope, honoring a nonlocal or global declaration for the target in that scope, if one exists. For the purpose of this rule the containing scope of a nested comprehension is the scope that contains the outermost comprehension. A lambda counts as a containing scope.

The motivation for this special case is twofold. First, it allows us to conveniently capture a “witness” for an any() expression, or a counterexample for all() , for example:

Second, it allows a compact way of updating mutable state from a comprehension, for example:

However, an assignment expression target name cannot be the same as a for -target name appearing in any comprehension containing the assignment expression. The latter names are local to the comprehension in which they appear, so it would be contradictory for a contained use of the same name to refer to the scope containing the outermost comprehension instead.

For example, [i := i+1 for i in range(5)] is invalid: the for i part establishes that i is local to the comprehension, but the i := part insists that i is not local to the comprehension. The same reason makes these examples invalid too:

While it’s technically possible to assign consistent semantics to these cases, it’s difficult to determine whether those semantics actually make sense in the absence of real use cases. Accordingly, the reference implementation [1] will ensure that such cases raise SyntaxError , rather than executing with implementation defined behaviour.

This restriction applies even if the assignment expression is never executed:

For the comprehension body (the part before the first “for” keyword) and the filter expression (the part after “if” and before any nested “for”), this restriction applies solely to target names that are also used as iteration variables in the comprehension. Lambda expressions appearing in these positions introduce a new explicit function scope, and hence may use assignment expressions with no additional restrictions.

Due to design constraints in the reference implementation (the symbol table analyser cannot easily detect when names are re-used between the leftmost comprehension iterable expression and the rest of the comprehension), named expressions are disallowed entirely as part of comprehension iterable expressions (the part after each “in”, and before any subsequent “if” or “for” keyword):

A further exception applies when an assignment expression occurs in a comprehension whose containing scope is a class scope. If the rules above were to result in the target being assigned in that class’s scope, the assignment expression is expressly invalid. This case also raises SyntaxError :

(The reason for the latter exception is the implicit function scope created for comprehensions – there is currently no runtime mechanism for a function to refer to a variable in the containing class scope, and we do not want to add such a mechanism. If this issue ever gets resolved this special case may be removed from the specification of assignment expressions. Note that the problem already exists for using a variable defined in the class scope from a comprehension.)

See Appendix B for some examples of how the rules for targets in comprehensions translate to equivalent code.

The := operator groups more tightly than a comma in all syntactic positions where it is legal, but less tightly than all other operators, including or , and , not , and conditional expressions ( A if C else B ). As follows from section “Exceptional cases” above, it is never allowed at the same level as = . In case a different grouping is desired, parentheses should be used.

The := operator may be used directly in a positional function call argument; however it is invalid directly in a keyword argument.

Some examples to clarify what’s technically valid or invalid:

Most of the “valid” examples above are not recommended, since human readers of Python source code who are quickly glancing at some code may miss the distinction. But simple cases are not objectionable:

This PEP recommends always putting spaces around := , similar to PEP 8 ’s recommendation for = when used for assignment, whereas the latter disallows spaces around = used for keyword arguments.)

In order to have precisely defined semantics, the proposal requires evaluation order to be well-defined. This is technically not a new requirement, as function calls may already have side effects. Python already has a rule that subexpressions are generally evaluated from left to right. However, assignment expressions make these side effects more visible, and we propose a single change to the current evaluation order:

  • In a dict comprehension {X: Y for ...} , Y is currently evaluated before X . We propose to change this so that X is evaluated before Y . (In a dict display like {X: Y} this is already the case, and also in dict((X, Y) for ...) which should clearly be equivalent to the dict comprehension.)

Most importantly, since := is an expression, it can be used in contexts where statements are illegal, including lambda functions and comprehensions.

Conversely, assignment expressions don’t support the advanced features found in assignment statements:

  • Multiple targets are not directly supported: x = y = z = 0 # Equivalent: (z := (y := (x := 0)))
  • Single assignment targets other than a single NAME are not supported: # No equivalent a [ i ] = x self . rest = []
  • Priority around commas is different: x = 1 , 2 # Sets x to (1, 2) ( x := 1 , 2 ) # Sets x to 1
  • Iterable packing and unpacking (both regular or extended forms) are not supported: # Equivalent needs extra parentheses loc = x , y # Use (loc := (x, y)) info = name , phone , * rest # Use (info := (name, phone, *rest)) # No equivalent px , py , pz = position name , phone , email , * other_info = contact
  • Inline type annotations are not supported: # Closest equivalent is "p: Optional[int]" as a separate declaration p : Optional [ int ] = None
  • Augmented assignment is not supported: total += tax # Equivalent: (total := total + tax)

The following changes have been made based on implementation experience and additional review after the PEP was first accepted and before Python 3.8 was released:

  • for consistency with other similar exceptions, and to avoid locking in an exception name that is not necessarily going to improve clarity for end users, the originally proposed TargetScopeError subclass of SyntaxError was dropped in favour of just raising SyntaxError directly. [3]
  • due to a limitation in CPython’s symbol table analysis process, the reference implementation raises SyntaxError for all uses of named expressions inside comprehension iterable expressions, rather than only raising them when the named expression target conflicts with one of the iteration variables in the comprehension. This could be revisited given sufficiently compelling examples, but the extra complexity needed to implement the more selective restriction doesn’t seem worthwhile for purely hypothetical use cases.

Examples from the Python standard library

env_base is only used on these lines, putting its assignment on the if moves it as the “header” of the block.

  • Current: env_base = os . environ . get ( "PYTHONUSERBASE" , None ) if env_base : return env_base
  • Improved: if env_base := os . environ . get ( "PYTHONUSERBASE" , None ): return env_base

Avoid nested if and remove one indentation level.

  • Current: if self . _is_special : ans = self . _check_nans ( context = context ) if ans : return ans
  • Improved: if self . _is_special and ( ans := self . _check_nans ( context = context )): return ans

Code looks more regular and avoid multiple nested if. (See Appendix A for the origin of this example.)

  • Current: reductor = dispatch_table . get ( cls ) if reductor : rv = reductor ( x ) else : reductor = getattr ( x , "__reduce_ex__" , None ) if reductor : rv = reductor ( 4 ) else : reductor = getattr ( x , "__reduce__" , None ) if reductor : rv = reductor () else : raise Error ( "un(deep)copyable object of type %s " % cls )
  • Improved: if reductor := dispatch_table . get ( cls ): rv = reductor ( x ) elif reductor := getattr ( x , "__reduce_ex__" , None ): rv = reductor ( 4 ) elif reductor := getattr ( x , "__reduce__" , None ): rv = reductor () else : raise Error ( "un(deep)copyable object of type %s " % cls )

tz is only used for s += tz , moving its assignment inside the if helps to show its scope.

  • Current: s = _format_time ( self . _hour , self . _minute , self . _second , self . _microsecond , timespec ) tz = self . _tzstr () if tz : s += tz return s
  • Improved: s = _format_time ( self . _hour , self . _minute , self . _second , self . _microsecond , timespec ) if tz := self . _tzstr (): s += tz return s

Calling fp.readline() in the while condition and calling .match() on the if lines make the code more compact without making it harder to understand.

  • Current: while True : line = fp . readline () if not line : break m = define_rx . match ( line ) if m : n , v = m . group ( 1 , 2 ) try : v = int ( v ) except ValueError : pass vars [ n ] = v else : m = undef_rx . match ( line ) if m : vars [ m . group ( 1 )] = 0
  • Improved: while line := fp . readline (): if m := define_rx . match ( line ): n , v = m . group ( 1 , 2 ) try : v = int ( v ) except ValueError : pass vars [ n ] = v elif m := undef_rx . match ( line ): vars [ m . group ( 1 )] = 0

A list comprehension can map and filter efficiently by capturing the condition:

Similarly, a subexpression can be reused within the main expression, by giving it a name on first use:

Note that in both cases the variable y is bound in the containing scope (i.e. at the same level as results or stuff ).

Assignment expressions can be used to good effect in the header of an if or while statement:

Particularly with the while loop, this can remove the need to have an infinite loop, an assignment, and a condition. It also creates a smooth parallel between a loop which simply uses a function call as its condition, and one which uses that as its condition but also uses the actual value.

An example from the low-level UNIX world:

Rejected alternative proposals

Proposals broadly similar to this one have come up frequently on python-ideas. Below are a number of alternative syntaxes, some of them specific to comprehensions, which have been rejected in favour of the one given above.

A previous version of this PEP proposed subtle changes to the scope rules for comprehensions, to make them more usable in class scope and to unify the scope of the “outermost iterable” and the rest of the comprehension. However, this part of the proposal would have caused backwards incompatibilities, and has been withdrawn so the PEP can focus on assignment expressions.

Broadly the same semantics as the current proposal, but spelled differently.

Since EXPR as NAME already has meaning in import , except and with statements (with different semantics), this would create unnecessary confusion or require special-casing (e.g. to forbid assignment within the headers of these statements).

(Note that with EXPR as VAR does not simply assign the value of EXPR to VAR – it calls EXPR.__enter__() and assigns the result of that to VAR .)

Additional reasons to prefer := over this spelling include:

  • In if f(x) as y the assignment target doesn’t jump out at you – it just reads like if f x blah blah and it is too similar visually to if f(x) and y .
  • import foo as bar
  • except Exc as var
  • with ctxmgr() as var

To the contrary, the assignment expression does not belong to the if or while that starts the line, and we intentionally allow assignment expressions in other contexts as well.

  • NAME = EXPR
  • if NAME := EXPR

reinforces the visual recognition of assignment expressions.

This syntax is inspired by languages such as R and Haskell, and some programmable calculators. (Note that a left-facing arrow y <- f(x) is not possible in Python, as it would be interpreted as less-than and unary minus.) This syntax has a slight advantage over ‘as’ in that it does not conflict with with , except and import , but otherwise is equivalent. But it is entirely unrelated to Python’s other use of -> (function return type annotations), and compared to := (which dates back to Algol-58) it has a much weaker tradition.

This has the advantage that leaked usage can be readily detected, removing some forms of syntactic ambiguity. However, this would be the only place in Python where a variable’s scope is encoded into its name, making refactoring harder.

Execution order is inverted (the indented body is performed first, followed by the “header”). This requires a new keyword, unless an existing keyword is repurposed (most likely with: ). See PEP 3150 for prior discussion on this subject (with the proposed keyword being given: ).

This syntax has fewer conflicts than as does (conflicting only with the raise Exc from Exc notation), but is otherwise comparable to it. Instead of paralleling with expr as target: (which can be useful but can also be confusing), this has no parallels, but is evocative.

One of the most popular use-cases is if and while statements. Instead of a more general solution, this proposal enhances the syntax of these two statements to add a means of capturing the compared value:

This works beautifully if and ONLY if the desired condition is based on the truthiness of the captured value. It is thus effective for specific use-cases (regex matches, socket reads that return '' when done), and completely useless in more complicated cases (e.g. where the condition is f(x) < 0 and you want to capture the value of f(x) ). It also has no benefit to list comprehensions.

Advantages: No syntactic ambiguities. Disadvantages: Answers only a fraction of possible use-cases, even in if / while statements.

Another common use-case is comprehensions (list/set/dict, and genexps). As above, proposals have been made for comprehension-specific solutions.

This brings the subexpression to a location in between the ‘for’ loop and the expression. It introduces an additional language keyword, which creates conflicts. Of the three, where reads the most cleanly, but also has the greatest potential for conflict (e.g. SQLAlchemy and numpy have where methods, as does tkinter.dnd.Icon in the standard library).

As above, but reusing the with keyword. Doesn’t read too badly, and needs no additional language keyword. Is restricted to comprehensions, though, and cannot as easily be transformed into “longhand” for-loop syntax. Has the C problem that an equals sign in an expression can now create a name binding, rather than performing a comparison. Would raise the question of why “with NAME = EXPR:” cannot be used as a statement on its own.

As per option 2, but using as rather than an equals sign. Aligns syntactically with other uses of as for name binding, but a simple transformation to for-loop longhand would create drastically different semantics; the meaning of with inside a comprehension would be completely different from the meaning as a stand-alone statement, while retaining identical syntax.

Regardless of the spelling chosen, this introduces a stark difference between comprehensions and the equivalent unrolled long-hand form of the loop. It is no longer possible to unwrap the loop into statement form without reworking any name bindings. The only keyword that can be repurposed to this task is with , thus giving it sneakily different semantics in a comprehension than in a statement; alternatively, a new keyword is needed, with all the costs therein.

There are two logical precedences for the := operator. Either it should bind as loosely as possible, as does statement-assignment; or it should bind more tightly than comparison operators. Placing its precedence between the comparison and arithmetic operators (to be precise: just lower than bitwise OR) allows most uses inside while and if conditions to be spelled without parentheses, as it is most likely that you wish to capture the value of something, then perform a comparison on it:

Once find() returns -1, the loop terminates. If := binds as loosely as = does, this would capture the result of the comparison (generally either True or False ), which is less useful.

While this behaviour would be convenient in many situations, it is also harder to explain than “the := operator behaves just like the assignment statement”, and as such, the precedence for := has been made as close as possible to that of = (with the exception that it binds tighter than comma).

Some critics have claimed that the assignment expressions should allow unparenthesized tuples on the right, so that these two would be equivalent:

(With the current version of the proposal, the latter would be equivalent to ((point := x), y) .)

However, adopting this stance would logically lead to the conclusion that when used in a function call, assignment expressions also bind less tight than comma, so we’d have the following confusing equivalence:

The less confusing option is to make := bind more tightly than comma.

It’s been proposed to just always require parentheses around an assignment expression. This would resolve many ambiguities, and indeed parentheses will frequently be needed to extract the desired subexpression. But in the following cases the extra parentheses feel redundant:

Frequently Raised Objections

C and its derivatives define the = operator as an expression, rather than a statement as is Python’s way. This allows assignments in more contexts, including contexts where comparisons are more common. The syntactic similarity between if (x == y) and if (x = y) belies their drastically different semantics. Thus this proposal uses := to clarify the distinction.

The two forms have different flexibilities. The := operator can be used inside a larger expression; the = statement can be augmented to += and its friends, can be chained, and can assign to attributes and subscripts.

Previous revisions of this proposal involved sublocal scope (restricted to a single statement), preventing name leakage and namespace pollution. While a definite advantage in a number of situations, this increases complexity in many others, and the costs are not justified by the benefits. In the interests of language simplicity, the name bindings created here are exactly equivalent to any other name bindings, including that usage at class or module scope will create externally-visible names. This is no different from for loops or other constructs, and can be solved the same way: del the name once it is no longer needed, or prefix it with an underscore.

(The author wishes to thank Guido van Rossum and Christoph Groth for their suggestions to move the proposal in this direction. [2] )

As expression assignments can sometimes be used equivalently to statement assignments, the question of which should be preferred will arise. For the benefit of style guides such as PEP 8 , two recommendations are suggested.

  • If either assignment statements or assignment expressions can be used, prefer statements; they are a clear declaration of intent.
  • If using assignment expressions would lead to ambiguity about execution order, restructure it to use statements instead.

The authors wish to thank Alyssa Coghlan and Steven D’Aprano for their considerable contributions to this proposal, and members of the core-mentorship mailing list for assistance with implementation.

Appendix A: Tim Peters’s findings

Here’s a brief essay Tim Peters wrote on the topic.

I dislike “busy” lines of code, and also dislike putting conceptually unrelated logic on a single line. So, for example, instead of:

instead. So I suspected I’d find few places I’d want to use assignment expressions. I didn’t even consider them for lines already stretching halfway across the screen. In other cases, “unrelated” ruled:

is a vast improvement over the briefer:

The original two statements are doing entirely different conceptual things, and slamming them together is conceptually insane.

In other cases, combining related logic made it harder to understand, such as rewriting:

as the briefer:

The while test there is too subtle, crucially relying on strict left-to-right evaluation in a non-short-circuiting or method-chaining context. My brain isn’t wired that way.

But cases like that were rare. Name binding is very frequent, and “sparse is better than dense” does not mean “almost empty is better than sparse”. For example, I have many functions that return None or 0 to communicate “I have nothing useful to return in this case, but since that’s expected often I’m not going to annoy you with an exception”. This is essentially the same as regular expression search functions returning None when there is no match. So there was lots of code of the form:

I find that clearer, and certainly a bit less typing and pattern-matching reading, as:

It’s also nice to trade away a small amount of horizontal whitespace to get another _line_ of surrounding code on screen. I didn’t give much weight to this at first, but it was so very frequent it added up, and I soon enough became annoyed that I couldn’t actually run the briefer code. That surprised me!

There are other cases where assignment expressions really shine. Rather than pick another from my code, Kirill Balunov gave a lovely example from the standard library’s copy() function in copy.py :

The ever-increasing indentation is semantically misleading: the logic is conceptually flat, “the first test that succeeds wins”:

Using easy assignment expressions allows the visual structure of the code to emphasize the conceptual flatness of the logic; ever-increasing indentation obscured it.

A smaller example from my code delighted me, both allowing to put inherently related logic in a single line, and allowing to remove an annoying “artificial” indentation level:

That if is about as long as I want my lines to get, but remains easy to follow.

So, in all, in most lines binding a name, I wouldn’t use assignment expressions, but because that construct is so very frequent, that leaves many places I would. In most of the latter, I found a small win that adds up due to how often it occurs, and in the rest I found a moderate to major win. I’d certainly use it more often than ternary if , but significantly less often than augmented assignment.

I have another example that quite impressed me at the time.

Where all variables are positive integers, and a is at least as large as the n’th root of x, this algorithm returns the floor of the n’th root of x (and roughly doubling the number of accurate bits per iteration):

It’s not obvious why that works, but is no more obvious in the “loop and a half” form. It’s hard to prove correctness without building on the right insight (the “arithmetic mean - geometric mean inequality”), and knowing some non-trivial things about how nested floor functions behave. That is, the challenges are in the math, not really in the coding.

If you do know all that, then the assignment-expression form is easily read as “while the current guess is too large, get a smaller guess”, where the “too large?” test and the new guess share an expensive sub-expression.

To my eyes, the original form is harder to understand:

This appendix attempts to clarify (though not specify) the rules when a target occurs in a comprehension or in a generator expression. For a number of illustrative examples we show the original code, containing a comprehension, and the translation, where the comprehension has been replaced by an equivalent generator function plus some scaffolding.

Since [x for ...] is equivalent to list(x for ...) these examples all use list comprehensions without loss of generality. And since these examples are meant to clarify edge cases of the rules, they aren’t trying to look like real code.

Note: comprehensions are already implemented via synthesizing nested generator functions like those in this appendix. The new part is adding appropriate declarations to establish the intended scope of assignment expression targets (the same scope they resolve to as if the assignment were performed in the block containing the outermost comprehension). For type inference purposes, these illustrative expansions do not imply that assignment expression targets are always Optional (but they do indicate the target binding scope).

Let’s start with a reminder of what code is generated for a generator expression without assignment expression.

  • Original code (EXPR usually references VAR): def f (): a = [ EXPR for VAR in ITERABLE ]
  • Translation (let’s not worry about name conflicts): def f (): def genexpr ( iterator ): for VAR in iterator : yield EXPR a = list ( genexpr ( iter ( ITERABLE )))

Let’s add a simple assignment expression.

  • Original code: def f (): a = [ TARGET := EXPR for VAR in ITERABLE ]
  • Translation: def f (): if False : TARGET = None # Dead code to ensure TARGET is a local variable def genexpr ( iterator ): nonlocal TARGET for VAR in iterator : TARGET = EXPR yield TARGET a = list ( genexpr ( iter ( ITERABLE )))

Let’s add a global TARGET declaration in f() .

  • Original code: def f (): global TARGET a = [ TARGET := EXPR for VAR in ITERABLE ]
  • Translation: def f (): global TARGET def genexpr ( iterator ): global TARGET for VAR in iterator : TARGET = EXPR yield TARGET a = list ( genexpr ( iter ( ITERABLE )))

Or instead let’s add a nonlocal TARGET declaration in f() .

  • Original code: def g (): TARGET = ... def f (): nonlocal TARGET a = [ TARGET := EXPR for VAR in ITERABLE ]
  • Translation: def g (): TARGET = ... def f (): nonlocal TARGET def genexpr ( iterator ): nonlocal TARGET for VAR in iterator : TARGET = EXPR yield TARGET a = list ( genexpr ( iter ( ITERABLE )))

Finally, let’s nest two comprehensions.

  • Original code: def f (): a = [[ TARGET := i for i in range ( 3 )] for j in range ( 2 )] # I.e., a = [[0, 1, 2], [0, 1, 2]] print ( TARGET ) # prints 2
  • Translation: def f (): if False : TARGET = None def outer_genexpr ( outer_iterator ): nonlocal TARGET def inner_generator ( inner_iterator ): nonlocal TARGET for i in inner_iterator : TARGET = i yield i for j in outer_iterator : yield list ( inner_generator ( range ( 3 ))) a = list ( outer_genexpr ( range ( 2 ))) print ( TARGET )

Because it has been a point of confusion, note that nothing about Python’s scoping semantics is changed. Function-local scopes continue to be resolved at compile time, and to have indefinite temporal extent at run time (“full closures”). Example:

This document has been placed in the public domain.

Source: https://github.com/python/peps/blob/main/peps/pep-0572.rst

Last modified: 2023-10-11 12:05:51 GMT

Python If-Else Statement Example

Quincy Larson

If-Else statements – AKA conditional logic – are the bedrock of programming. And Python has these in spades.

Python offers several options for evaluating variables, their states, and whether specific conditions are met:

  • Vanilla if-else statements
  • if statements without the else part
  • nested if-else statements
  • else-if or elif statements
  • and looped if-else statements in the form of for-else and while-else

We'll talk about all of these, and also explain the extremely useful double-equals == operator.

How do you write an if-else statement in Python?

If you're just looking for an example to copy-paste, here is a super simple if-else statement in Python:

Note that the fact that Python is a whitespace-sensitive ensures that these if-else statements are easy to read – even when they get nested several layers deep.

With that out of the way, let's talk a bit more about conditional logic, and why if-else statements are so important to Python and other programming languages.

How do we use the if-else statement?

If-else statements are a form of conditional logic. Essentially, what that means is

  • We test a condition. For example, whether a given variable equals another given variable.
  • If the condition is true, we execute the following block of code.
  • And if the condition is false, we execute a different block of code.

This is absolutely critical to any sort of programming. You cannot have turing-complete programming languages without some sort of conditional logic. In Python, that means lots of if-else statements.

How is if statement different from if else statement in Python?

So you don't technically need the else part of the if-else statement. For example:

To see how this works, here is the Python REPL:

As you can see, this is sort of like an if-else statement with an invisible else . If the else part was there, and the condition was not met, it would just be like "OK. Carry on then."

What is the difference between Else and Elif construct of IF statement?

If you want to have more potential conditions, you can use an elif statement.

Here is an example elif statement:

You'll note that the elif operator appears between the initial if and else operators.

Also note that you can use as many elif as you want.

What is for else and while else in Python?

You can combine conditional logic with loops by using a for else or while else statement.

Here is an example for else statement that hits the break and exits:

And here is the same for if statement that starts from a higher number, which will skip the break event and finish. Take a look at the code and its output:

Can you have multiple if statements in Python?

Absolutely. You can have as many nested if statements as you want. Be careful, though. This can lead to the so-called "pyramid of doom."

Here's an example of nested if statements:

Notice how there are two if-else statements, but one of them is nested inside the other. This is OK for a lay or two, but it can get confusing quickly:

Can you have 3 conditions in an if statement?

Yes. But if you do this, it probably makes sense to use some elif operators in your statement for clarity.

Here is an example if statement with 3 conditions:

What does == mean in Python?

The Python == operator – also known as the equality operator – is a comparison operator that returns True if both of the operands (the variables or values on the left and the right of the == ) are equal. Otherwise it will return False.

This is an extremely common tool for crafting if statements and other conditional logic.

Learn it. Know it. Love it.

I hope you learned a lot about if statements.

I sure did in dusting off my Python knowledge and writing this tutorial. I hope you've found this helpful.

If you want to learn more about Python programming, and technology in general, try freeCodeCamp's core coding curriculum . It's free.

Read more posts .

If you read this far, thank the author to show them you care. Say Thanks

Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started

How to Write the Python if Statement in one Line

Author's photo

  • online practice

Have you ever heard of writing a Python if statement in a single line? Here, we explore multiple ways to do exactly that, including using conditional expressions in Python.

The if statement is one of the most fundamental statements in Python. In this article, we learn how to write the Python if in one line.

The if is a key piece in writing Python code. It allows developers to control the flow and logic of their code based on information received at runtime. However, many Python developers do not know they may reduce the length and complexity of their if statements by writing them in a single line.

For this article, we assume you’re somewhat familiar with Python conditions and comparisons. If not, don’t worry! Our Python Basics Course will get you up to speed in no time. This course is included in the Python Basics Track , a full-fledged Python learning track designed for complete beginners.

We start with a recap on how Python if statements work. Then, we explore some examples of how to write if statements in a single line. Let’s get started!

How the if Statement Works in Python

Let’s start with the basics. An if statement in Python is used to determine whether a condition is True or False . This information can then be used to perform specific actions in the code, essentially controlling its logic during execution.

The structure of the basic if statement is as follows:

The <expression> is the code that evaluates to either True or False . If this code evaluates to True, then the code below (represented by <perform_action> ) executes.

Python uses whitespaces to indicate which lines are controlled by the if statement. The if statement controls all indented lines below it. Typically, the indentation is set to four spaces (read this post if you’re having trouble with the indentation ).

As a simple example, the code below prints a message if and only if the current weather is sunny:

The if statement in Python has two optional components: the elif statement, which executes only if the preceding if/elif statements are False ; and the else statement, which executes only if all of the preceding if/elif statements are False. While we may have as many elif statements as we want, we may only have a single else statement at the very end of the code block.

Here’s the basic structure:

Here’s how our previous example looks after adding elif and else statements. Change the value of the weather variable to see a different message printed:

How to Write a Python if in one Line

Writing an if statement in Python (along with the optional elif and else statements) uses a lot of whitespaces. Some people may find it confusing or tiresome to follow each statement and its corresponding indented lines.

To overcome this, there is a trick many Python developers often overlook: write an if statement in a single line !

Though not the standard, Python does allow us to write an if statement and its associated action in the same line. Here’s the basic structure:

As you can see, not much has changed. We simply need to “pull” the indented line <perform_action> up to the right of the colon character ( : ). It’s that simple!

Let’s check it with a real example. The code below works as it did previously despite the if statement being in a single line. Test it out and see for yourself:

Writing a Python if Statement With Multiple Actions in one Line

That’s all well and good, but what if my if statement has multiple actions under its control? When using the standard indentation, we separate different actions in multiple indented lines as the structure below shows:

Can we do this in a single line? The surprising answer is yes! We use semicolons to separate each action in the same line as if placed in different lines.

Here’s how the structure looks:

And an example of this functionality:

Have you noticed how each call to the print() function appears in its own line? This indicates we have successfully executed multiple actions from a single line. Nice!

By the way, interested in learning more about the print() function? We have an article on the ins and outs of the print() function .

Writing a Full Python if/elif/else Block Using Single Lines

You may have seen this coming, but we can even write elif and else statements each in a single line. To do so, we use the same syntax as writing an if statement in a single line.

Here’s the general structure:

Looks simple, right? Depending on the content of your expressions and actions, you may find this structure easier to read and understand compared to the indented blocks.

Here’s our previous example of a full if/elif/else block, rewritten as single lines:

Using Python Conditional Expressions to Write an if/else Block in one Line

There’s still a final trick to writing a Python if in one line. Conditional expressions in Python (also known as Python ternary operators) can run an if/else block in a single line.

A conditional expression is even more compact! Remember it took at least two lines to write a block containing both if and else statements in our last example.

In contrast, here’s how a conditional expression is structured:

The syntax is somewhat harder to follow at first, but the basic idea is that <expression> is a test. If the test evaluates to True , then <value_if_true> is the result. Otherwise, the expression results in <value_if_false> .

As you can see, conditional expressions always evaluate to a single value in the end. They are not complete replacements for an if/elif/else block. In fact, we cannot have elif statements in them at all. However, they’re most helpful when determining a single value depending on a single condition.

Take a look at the code below, which determines the value of is_baby depending on whether or not the age is below five:

This is the exact use case for a conditional expression! Here’s how we rewrite this if/else block in a single line:

Much simpler!

Go Even Further With Python!

We hope you now know many ways to write a Python if in one line. We’ve reached the end of the article, but don’t stop practicing now!

If you do not know where to go next, read this post on how to get beyond the basics in Python . If you’d rather get technical, we have a post on the best code editors and IDEs for Python . Remember to keep improving!

You may also like

python if statement variable assignment

How Do You Write a SELECT Statement in SQL?

python if statement variable assignment

What Is a Foreign Key in SQL?

python if statement variable assignment

Enumerate and Explain All the Basic Elements of an SQL Query

previous episode

Python for absolute beginners, next episode, variables and assignment.

Overview Teaching: 15 min Exercises: 15 min Questions How can I store data in programs? Objectives Write scripts that assign values to variables and perform calculations with those values. Correctly trace value changes in scripts that use assignment.

Use variables to store values

Variables are one of the fundamental building blocks of Python. A variable is like a tiny container where you store values and data, such as filenames, words, numbers, collections of words and numbers, and more.

The variable name will point to a value that you “assign” it. You might think about variable assignment like putting a value “into” the variable, as if the variable is a little box 🎁

(In fact, a variable is not a container as such but more like an adress label that points to a container with a given value. This difference will become relevant once we start talking about lists and mutable data types.)

You assign variables with an equals sign ( = ). In Python, a single equals sign = is the “assignment operator.” (A double equals sign == is the “real” equals sign.)

  • Variables are names for values.
  • In Python the = symbol assigns the value on the right to the name on the left.
  • The variable is created when a value is assigned to it.
  • Here, Python assigns an age to a variable age and a name in quotation marks to a variable first_name :

Variable names

Variable names can be as long or as short as you want, but there are certain rules you must follow.

  • Cannot start with a digit.
  • Cannot contain spaces, quotation marks, or other punctuation.
  • May contain an underscore (typically used to separate words in long variable names).
  • Having an underscore at the beginning of a variable name like _alistairs_real_age has a special meaning. So we won’t do that until we understand the convention.
  • The standard naming convention for variable names in Python is the so-called “snake case”, where each word is separated by an underscore. For example my_first_variable . You can read more about naming conventions in Python here .

Use meaningful variable names

Python doesn’t care what you call variables as long as they obey the rules (alphanumeric characters and the underscore). As you start to code, you will almost certainly be tempted to use extremely short variables names like f . Your fingers will get tired. Your coffee will wear off. You will see other people using variables like f . You’ll promise yourself that you’ll definitely remember what f means. But you probably won’t.

So, resist the temptation of bad variable names! Clear and precisely-named variables will:

  • Make your code more readable (both to yourself and others).
  • Reinforce your understanding of Python and what’s happening in the code.
  • Clarify and strengthen your thinking.

Use meaningful variable names to help other people understand what the program does. The most important “other person” is your future self!

Python is case-sensitive

Python thinks that upper- and lower-case letters are different, so Name and name are different variables. There are conventions for using upper-case letters at the start of variable names so we will use lower-case letters for now.

Off-Limits Names

The only variable names that are off-limits are names that are reserved by, or built into, the Python programming language itself — such as print , True , and list . Some of these you can overwrite into variable names (not ideal!), but Jupyter Lab (and many other environments and editors) will catch this by colour coding your variable. If your would-be variable is colour-coded green, rethink your name choice. This is not something to worry too much about. You can get the object back by resetting your kernel.

Use print() to display values

We can check to see what’s “inside” variables by running a cell with the variable’s name. This is one of the handiest features of a Jupyter notebook. Outside the Jupyter environment, you would need to use the print() function to display the variable.

You can run the print() function inside the Jupyter environment, too. This is sometimes useful because Jupyter will only display the last variable in a cell, while print() can display multiple variables. Additionally, Jupyter will display text with \n characters (which means “new line”), while print() will display the text appropriately formatted with new lines.

  • Python has a built-in function called print() that prints things as text.
  • Provide values to the function (i.e., the things to print) in parentheses.
  • To add a string to the printout, wrap the string in single or double quotations.
  • The values passed to the function are called ‘arguments’ and are separated by commas.
  • When using the print() function, we can also separate with a ‘+’ sign. However, when using ‘+’ we have to add spaces in between manually.
  • print() automatically puts a single space between items to separate them.
  • And wraps around to a new line at the end.

Variables must be created before they are used

If a variable doesn’t exist yet, or if the name has been misspelled, Python reports an error (unlike some languages, which “guess” a default value).

The last line of an error message is usually the most informative. This message lets us know that there is no variable called eye_color in the script.

Variables Persist Between Cells Variables defined in one cell exist in all other cells once executed, so the relative location of cells in the notebook do not matter (i.e., cells lower down can still affect those above). Notice the number in the square brackets [ ] to the left of the cell. These numbers indicate the order, in which the cells have been executed. Cells with lower numbers will affect cells with higher numbers as Python runs the cells chronologically. As a best practice, we recommend you keep your notebook in chronological order so that it is easier for the human eye to read and make sense of, as well as to avoid any errors if you close and reopen your project, and then rerun what you have done. Remember: Notebook cells are just a way to organize a program! As far as Python is concerned, all of the source code is one long set of instructions.

Variables can be used in calculations

  • We can use variables in calculations just as if they were values. Remember, we assigned 42 to age a few lines ago.

This code works in the following way. We are reassigning the value of the variable age by taking its previous value (42) and adding 3, thus getting our new value of 45.

Use an index to get a single character from a string

  • The characters (individual letters, numbers, and so on) in a string are ordered. For example, the string ‘AB’ is not the same as ‘BA’. Because of this ordering, we can treat the string as a list of characters.
  • Each position in the string (first, second, etc.) is given a number. This number is called an index or sometimes a subscript.
  • Indices are numbered from 0 rather than 1.
  • Use the position’s index in square brackets to get the character at that position.

Use a slice to get a substring

A part of a string is called a substring. A substring can be as short as a single character. A slice is a part of a string (or, more generally, any list-like thing). We take a slice by using [start:stop] , where start is replaced with the index of the first element we want and stop is replaced with the index of the element just after the last element we want. Mathematically, you might say that a slice selects [start:stop] . The difference between stop and start is the slice’s length. Taking a slice does not change the contents of the original string. Instead, the slice is a copy of part of the original string.

Use the built-in function len() to find the length of a string

The built-in function len() is used to find the length of a string (and later, of other data types, too).

Note that the result is 6 and not 7. This is because it is the length of the value of the variable (i.e. 'helium' ) that is being counted and not the name of the variable (i.e. element )

Also note that nested functions are evaluated from the inside out, just like in mathematics. Thus, Python first reads the len() function, then the print() function.

Choosing a Name Which is a better variable name, m , min , or minutes ? Why? Hint: think about which code you would rather inherit from someone who is leaving the library: ts = m * 60 + s tot_sec = min * 60 + sec total_seconds = minutes * 60 + seconds Solution minutes is better because min might mean something like “minimum” (and actually does in Python, but we haven’t seen that yet).
Swapping Values Draw a table showing the values of the variables in this program after each statement is executed. In simple terms, what do the last three lines of this program do? x = 1.0 y = 3.0 swap = x x = y y = swap Solution swap = x # x->1.0 y->3.0 swap->1.0 x = y # x->3.0 y->3.0 swap->1.0 y = swap # x->3.0 y->1.0 swap->1.0 These three lines exchange the values in x and y using the swap variable for temporary storage. This is a fairly common programming idiom.
Predicting Values What is the final value of position in the program below? (Try to predict the value without running the program, then check your prediction.) initial = "left" position = initial initial = "right" Solution initial = "left" # Initial is assigned the string "left" position = initial # Position is assigned the variable initial, currently "left" initial = "right" # Initial is assigned the string "right" print(position) left The last assignment to position was “left”
Can you slice integers? If you assign a = 123 , what happens if you try to get the second digit of a ? Solution Numbers are not stored in the written representation, so they can’t be treated like strings. a = 123 print(a[1]) TypeError: 'int' object is not subscriptable
Slicing What does the following program print? library_name = 'social sciences' print('library_name[1:3] is:', library_name[1:3]) If thing is a variable name, low is a low number, and high is a high number: What does thing[low:high] do? What does thing[low:] (without a value after the colon) do? What does thing[:high] (without a value before the colon) do? What does thing[:] (just a colon) do? What does thing[number:negative-number] do? Solution library_name[1:3] is: oc It will slice the string, starting at the low index and ending an element before the high index It will slice the string, starting at the low index and stopping at the end of the string It will slice the string, starting at the beginning on the string, and ending an element before the high index It will print the entire string It will slice the string, starting the number index, and ending a distance of the absolute value of negative-number elements from the end of the string
Key Points Use variables to store values. Use meaningful variable names. Python is case-sensitive. Use print() to display values. Variables must be created before they are used. Variables persist between cells. Variables can be used in calculations. Use an index to get a single character from a string. Use a slice to get a substring. Use the built-in function len to find the length of a string.

Conditional expression (ternary operator) in Python

Python has a conditional expression (sometimes called a "ternary operator"). You can write operations like if statements in one line with conditional expressions.

  • 6. Expressions - Conditional expressions — Python 3.11.3 documentation

Basics of the conditional expression (ternary operator)

If ... elif ... else ... by conditional expressions, list comprehensions and conditional expressions, lambda expressions and conditional expressions.

See the following article for if statements in Python.

  • Python if statements (if, elif, else)

In Python, the conditional expression is written as follows.

The condition is evaluated first. If condition is True , X is evaluated and its value is returned, and if condition is False , Y is evaluated and its value is returned.

If you want to switch the value based on a condition, simply use the desired values in the conditional expression.

If you want to switch between operations based on a condition, simply describe each corresponding expression in the conditional expression.

An expression that does not return a value (i.e., an expression that returns None ) is also acceptable in a conditional expression. Depending on the condition, either expression will be evaluated and executed.

The above example is equivalent to the following code written with an if statement.

You can also combine multiple conditions using logical operators such as and or or .

  • Boolean operators in Python (and, or, not)

By combining conditional expressions, you can write an operation like if ... elif ... else ... in one line.

However, it is difficult to understand, so it may be better not to use it often.

The following two interpretations are possible, but the expression is processed as the first one.

In the sample code below, which includes three expressions, the first expression is interpreted like the second, rather than the third:

By using conditional expressions in list comprehensions, you can apply operations to the elements of the list based on the condition.

See the following article for details on list comprehensions.

  • List comprehensions in Python

Conditional expressions are also useful when you want to apply an operation similar to an if statement within lambda expressions.

In the example above, the lambda expression is assigned to a variable for convenience, but this is not recommended by PEP8.

Refer to the following article for more details on lambda expressions.

  • Lambda expressions in Python

Related Categories

Related articles.

  • Shallow and deep copy in Python: copy(), deepcopy()
  • Composite two images according to a mask image with Python, Pillow
  • OpenCV, NumPy: Rotate and flip image
  • pandas: Check if DataFrame/Series is empty
  • Check pandas version: pd.show_versions
  • Python if statement (if, elif, else)
  • pandas: Find the quantile with quantile()
  • Handle date and time with the datetime module in Python
  • Get image size (width, height) with Python, OpenCV, Pillow (PIL)
  • Convert between Unix time (Epoch time) and datetime in Python
  • Convert BGR and RGB with Python, OpenCV (cvtColor)
  • Matrix operations with NumPy in Python
  • pandas: Replace values in DataFrame and Series with replace()
  • Uppercase and lowercase strings in Python (conversion and checking)
  • Calculate mean, median, mode, variance, standard deviation in Python

VIDEO

  1. Python

  2. Python Statement, Indentation and Comments

  3. introduction to python if statement #20

  4. Identify the output of the following python statement.#python #coding #12th #idle

  5. Python Statements and Python Comments💬 #ai #python #datascience #languagelearning #programming

  6. How to do "if-for" statement in python? #shorts

COMMENTS

  1. python

    If it helps, you can think of a variable in python as a "box of stuff" (the value), with a post-it note stuck to the side with a name written on it (the name). On the first line of code in your question, you created a box of stuff (the dictionary) and stuck the name "dict1" to it.

  2. How to find first non-blank string variable during string assignment

    I have Python 3.12 on Windows 10. I work with spreadsheets. I read each row one at a time, and grab one piece of data from that row, let's say a job number, which could be in column A, B or C. Yes, the spreadsheet is a mess, I can't change that. I have to work with what I'm given. But the preferred order I look for the job number in the columns is B, A, C. I need to look for a job in ...

  3. Defining a symbolic syntax for referring to assignment targets

    __target_text__ could replace @'' for both identifier assignment and tuple assignment ( __target_name__ wouldn't match the latter use case) Sounds good indeed. With the name __target_text__ we wouldn't have to worry about a plural form. I doubt you could reasonably use that form to map function parameters to local variables of the same name ...

  4. How to verify pyodbc database connection is still open?

    I have Python v3.12.1 on Windows 10. In the beginning of my program I open a connection to a pyodbc database and store the connection in an options class variable. It is stored in options.dbconn. This allows me to have one connection and reuse it in many functions, putting less stress on the database server. I have a db connection timeout set to 900 seconds. The connection is initially opened ...

  5. Google Colab

    Notebooks consist of so-called code cells, blocks of one or more Python instructions. For example, here is a code cell that stores the result of a computation (the number of seconds in a day) in a variable and prints its value: ... Notice the two spaces before print in the snippet with the if, elif, else statements. These spaces are called ...

  6. Learn to Program: The Fundamentals

    Installing Python • 2 minutes; Python as a Calculator • 10 minutes; Python and Computer Memory • 2 minutes; Variables • 7 minutes; Visualizing Assignment Statements • 2 minutes; Built-in Functions • 5 minutes; Defining Functions • 6 minutes

  7. Audrey

    6 likes, 2 comments - coder__python_z on August 27, 2024: "Here is the answer!!六‍ Answer: B) `x = 5` Explanation: In Python, the assignment operator (=) is used to assign a value to a variable. The correct syntax is `variable_name = value`, which in this case is `x = 5`. Note: `x == 5` is a comparison operator, used to check if `x` is equal to 5. `x -> 5` and `x <- 5` are not valid Python ...

  8. python

    No. Assignment in Python is a statement, not an expression. Share. Improve this answer. ... # This only works in Python 2.x True = some_variable print True # returns 5 In Python 3 True and False are keywords, so no risk anymore. Share. Improve this answer. Follow answered Nov 11, 2013 at 16:40. user2979916 ...

  9. Python Conditional Assignment (in 3 Ways)

    Let's see a code snippet to understand it better. a = 10. b = 20 # assigning value to variable c based on condition. c = a if a > b else b. print(c) # output: 20. You can see we have conditionally assigned a value to variable c based on the condition a > b. 2. Using if-else statement.

  10. Python if, if...else Statement (With Examples)

    Python if Statement. An if statement executes a block of code only when the specified condition is met.. Syntax. if condition: # body of if statement. Here, condition is a boolean expression, such as number > 5, that evaluates to either True or False. If condition evaluates to True, the body of the if statement is executed.; If condition evaluates to False, the body of the if statement will be ...

  11. How To Use Assignment Expressions in Python

    For example, assignment expressions using the := syntax allow variables to be assigned inside of if statements, which can often produce shorter and more compact sections of Python code by eliminating variable assignments in lines preceding or following the if statement. In this tutorial, you will use assignment expressions in several examples ...

  12. Python's Assignment Operator: Write Robust Assignments

    Here, variable represents a generic Python variable, while expression represents any Python object that you can provide as a concrete value—also known as a literal—or an expression that evaluates to a value. To execute an assignment statement like the above, Python runs the following steps: Evaluate the right-hand expression to produce a concrete value or object.

  13. Python Conditional Variable Setting

    What I mean is this: value = 'Test' if 1 == 1. Where it would hopefully set value to 'Test' if the condition (1 == 1) is true. And with that, I was going to test for multiple conditions to set different variables, like this: value = ('test' if 1 == 1, 'testtwo' if 2 == 2) And so on for just a few conditions.

  14. variable assignment

    If you want to use the result of a computation twice, put it in a temporary variable: value = info.findNext("b") value = value if value else "Oompa Loompa". Once you do this, it becomes clear that you're doing something silly, and in fact the pythonic way to write this is: value = info.findNext("b") if not value: value = "Oompa Loompa".

  15. Conditional Statements in Python

    In the form shown above: <expr> is an expression evaluated in a Boolean context, as discussed in the section on Logical Operators in the Operators and Expressions in Python tutorial. <statement> is a valid Python statement, which must be indented. (You will see why very soon.) If <expr> is true (evaluates to a value that is "truthy"), then <statement> is executed.

  16. Conditional Statements

    In its simplest form, a conditional statement requires only an if clause. else and elif clauses can only follow an if clause. # A conditional statement consisting of # an "if"-clause, only. x = -1 if x < 0: x = x ** 2 # x is now 1. Similarly, conditional statements can have an if and an else without an elif:

  17. How to Use Conditional Statements in Python

    Conditional statements are an essential part of programming in Python. They allow you to make decisions based on the values of variables or the result of comparisons. In this article, we'll explore how to use if, else, and elif statements in Python, along with some examples of how to use them in practice. How to Use the if Statement in Python

  18. Python's nested if statement explained (with examples) · Kodify

    Default pattern: if statement inside if. There are two main ways to make a nested if statement. The first option is to put the if statement inside an ifcode block. The other option is to place the if statement in the elsecode of an if/else statement. So the first approach has us place an if statement inside another.

  19. How to Use IF Statements in Python (if, else, elif, and more

    Output: x is equal to y. Python first checks if the condition x < y is met. It isn't, so it goes on to the second condition, which in Python, we write as elif, which is short for else if. If the first condition isn't met, check the second condition, and if it's met, execute the expression. Else, do something else.

  20. 7. Simple statements

    An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right. ... in a single statement, of a variable or attribute annotation and an optional assignment ...

  21. 3.1. If Statements

    In any event, when you have finished with the if statement (whether it actually does anything or not), go on to the next statement that is not indented under the if. In this case that is the statement printing "Thank you". The general Python syntax for a simple if statement is. if condition : indentedStatementBlock.

  22. PEP 572

    However, this would be the only place in Python where a variable's scope is encoded into its name, making refactoring harder. Adding a where: to any statement to create local name bindings: value = x ** 2 + 2 * x where: x = spam (1, 4, 7, q) ... If either assignment statements or assignment expressions can be used, prefer statements; they are ...

  23. Python If-Else Statement Example

    Be careful, though. This can lead to the so-called "pyramid of doom." Here's an example of nested if statements: if x == 5: if y == 10: print("x is 5 and y is 10") else: print("x is 5 and y is something else") else: print("x is something else") Notice how there are two if-else statements, but one of them is nested inside the other.

  24. How to Write the Python if Statement in one Line

    You may have seen this coming, but we can even write elif and else statements each in a single line. To do so, we use the same syntax as writing an if statement in a single line. Here's the general structure: if <expression_01>: <perform_action_01>. elif <expression_02>: <perform_action_02>.

  25. Variables and Assignment

    In Python, a single equals sign = is the "assignment operator." (A double equals sign == is the "real" equals sign.) Variables are names for values. In Python the = symbol assigns the value on the right to the name on the left. The variable is created when a value is assigned to it. Here, Python assigns an age to a variable age and a ...

  26. Conditional expression (ternary operator) in Python

    Basics of the conditional expression (ternary operator) In Python, the conditional expression is written as follows. X if condition else Y. The condition is evaluated first. If condition is True, X is evaluated and its value is returned, and if condition is False, Y is evaluated and its value is returned. If you want to switch the value based ...