• Python »
  • 3.12.4 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

Stack Exchange Network

Stack Exchange network consists of 183 Q&A communities including Stack Overflow , the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Q&A for work

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

What is the benefit of having the assignment operator return a value?

I'm developing a language which I intend to replace both Javascript and PHP. (I can't see any problem with this. It's not like either of these languages have a large install base.)

One of the things I wanted to change was to turn the assignment operator into an assignment command, removing the ability to make use of the returned value.

I know that this would mean that those one-line functions that C people love so much would no longer work. I figured (with little evidence beyond my personal experience) that the vast majority of times this happened, it was really intended to be comparison operation.

Or is it? Are there any practical uses of the assignment operator's return value that could not be trivially rewritten? (For any language that has such a concept.)

  • language-agnostic

billpg's user avatar

  • 12 JS and PHP do not have a large "install base"? –  mhr Commented Feb 13, 2014 at 12:33
  • 47 @mri I suspect sarcasm. –  Andy Hunt Commented Feb 13, 2014 at 12:41
  • 12 The only useful case I can remember is while((x = getValue()) != null) {} . Replacements will be uglier since you'll need to either use break or repeat the x = getValue assignment. –  CodesInChaos Commented Feb 13, 2014 at 13:04
  • 12 @mri Ooh no, I hear those two languages are just trivial things without any significant investment at all. Once the few people who insist on using JS see my language, they will switch over to mine and never have to write === again. I'm equally sure the browser makers will immediately roll out an update that includes my language alongside JS. :) –  billpg Commented Feb 13, 2014 at 14:58
  • 4 I would suggest to you that if your intention is to enhance an existing language and you intend it to be adopted widely then 100% backwards compatibility with the existing language is good. See TypeScript as an exemplar. If your intention is to provide a better alternative to an existing language then you have a much harder problem. A new language has to solve an existing realistic problem much much better than the existing language in order to pay for the cost of switching. Learning a language is an investment and it needs to pay off. –  Eric Lippert Commented Feb 13, 2014 at 18:57

9 Answers 9

Technically, some syntactic sugar can be worth keeping even if it can trivially be replaced, if it improves readability of some common operation. But assignment-as-expression does not fall under that. The danger of typo-ing it in place of a comparison means it's rarely used (sometimes even prohibited by style guides) and provokes a double take whenever it is used. In other words, the readability benefits are small in number and magnitude.

A look at existing languages that do this may be worthwhile.

  • Java and C# keep assignment an expression but remove the pitfall you mention by requiring conditions to evaluate to booleans. This mostly seems to work well, though people occasionally complain that this disallows conditions like if (x) in place of if (x != null) or if (x != 0) depending on the type of x .
  • Python makes assignment a proper statement instead of an expression. Proposals for changing this occasionally reach the python-ideas mailing list, but my subjective impression is that this happens more rarely and generates less noise each time compared to other "missing" features like do-while loops, switch statements, multi-line lambdas, etc.

However, Python allows one special case, assigning to multiple names at once: a = b = c . This is considered a statement equivalent to b = c; a = b , and it's occasionally used, so it may be worth adding to your language as well (but I wouldn't sweat it, since this addition should be backwards-compatible).

  • 5 +1 for bringing up a = b = c which the other answers do not really bring up. –  Leo Commented Feb 13, 2014 at 15:53
  • 6 A third resolution is to use a different symbol for assignment. Pascal uses := for assignment. –  Brian Commented Feb 13, 2014 at 19:08
  • 6 @Brian: Indeed, as does C#. = is assignment, == is comparison. –  Marjan Venema Commented Feb 13, 2014 at 19:47
  • 3 In C#, something like if (a = true) will throw a C4706 warning ( The test value in a conditional expression was the result of an assignment. ). GCC with C will likewise throw a warning: suggest parentheses around assignment used as truth value [-Wparentheses] . Those warnings can be silenced with an extra set of parentheses, but they are there to encourage explicitly indicating the assignment was intentional. –  Bob Commented Feb 13, 2014 at 22:27
  • 2 @delnan Just a somewhat generic comment, but it was sparked by "remove the pitfall you mention by requiring conditions to evaluate to booleans" - a = true does evaluate to a Boolean and is therefore not an error, but it also raises a related warning in C#. –  Bob Commented Feb 13, 2014 at 23:48
Are there any practical uses of the assignment operator's return value that could not be trivially rewritten?

Generally speaking, no. The idea of having the value of an assignment expression be the value that was assigned means that we have an expression which may be used for both its side effect and its value , and that is considered by many to be confusing.

Common usages are typically to make expressions compact:

has the semantics in C# of "convert z to the type of y, assign the converted value to y, the converted value is the value of the expression, convert that to the type of x, assign to x".

But we are already in the realm of impertative side effects in a statement context, so there's really very little compelling benefit to that over

Similarly with

being a shorthand for

Again, in the original code we are using an expression both for its side effects and its value, and we are making a statement that has two side effects instead of one. Both are smelly; try to have one side effect per statement, and use expressions for their values, not for their side effects.

I'm developing a language which I intend to replace both Javascript and PHP.

If you really want to be bold and emphasize that assignment is a statement and not an equality, then my advice is: make it clearly an assignment statement .

There, done. Or

or even better:

Or even better still

There's absolutely no way that any of those are going to be confused with x == 1 .

Eric Lippert's user avatar

  • 1 Is the world ready for non-ASCII Unicode symbols in programming languages? –  billpg Commented Feb 14, 2014 at 11:25
  • As much as I would love what you suggest, one of my goals is that most "well written" JavaScript can be ported over with little or no modification. –  billpg Commented Feb 14, 2014 at 11:44
  • 2 @billpg: Is the world ready ? I don't know -- was the world ready for APL in 1964, decades before the invention of Unicode? Here's a program in APL that picks a random permutation of six numbers out of the first 40: x[⍋x←6?40] APL required its own special keyboard, but it was a pretty successful language. –  Eric Lippert Commented Feb 14, 2014 at 15:17
  • @billpg: Macintosh Programmer's Workshop used non-ASCII symbols for things like regex tags or redirection of stderr. On the other hand, MPW had the advantage that the Macintosh made it easy to type non-ASCII characters. I must confess some puzzlement as to why the US keyboard driver doesn't provide any decent means of typing any non-ASCII characters. Not only does Alt-number entry require looking up character codes--in many applications it doesn't even work. –  supercat Commented Feb 14, 2014 at 18:20
  • Hm, why would one prefer to assign "to the right" like a+b*c --> x ? This looks strange to me. –  Ruslan Commented Aug 21, 2015 at 10:49

Many languages do choose the route of making assignment a statement rather than an expression, including Python:

and Golang:

Other languages don't have assignment, but rather scoped bindings, e.g. OCaml:

However, let is an expression itself.

The advantage of allowing assignment is that we can directly check the return value of a function inside the conditional, e.g. in this Perl snippet:

Perl additionally scopes the declaration to that conditional only, which makes it very useful. It will also warn if you assign inside a conditional without declaring a new variable there – if ($foo = $bar) will warn, if (my $foo = $bar) will not.

Making the assignment in another statement is usually sufficient, but can bring scoping problems:

Golang heavily relies on return values for error checking. It therefore allows a conditional to take an initialization statement:

Other languages use a type system to disallow non-boolean expressions inside a conditional:

Of course that fails when using a function that returns a boolean.

We now have seen different mechanisms to defend against accidental assignment:

  • Disallow assignment as an expression
  • Use static type checking
  • Assignment doesn't exist, we only have let bindings
  • Allow an initialization statement, disallow assignment otherwise
  • Disallow assignment inside a conditional without declaration

I've ranked them in order of ascending preference – assignments inside expressions can be useful (and it's simple to circumvent Python's problems by having an explicit declaration syntax, and a different named argument syntax). But it's ok to disallow them, as there are many other options to the same effect.

Bug-free code is more important than terse code.

amon's user avatar

  • +1 for "Disallow assignment as an expression". The use-cases for assignment-as-an-expression don't justify the potential for bugs and readability issues. –  poke Commented Feb 14, 2014 at 17:00

You said "I figured (with little evidence beyond my personal experience) that the vast majority of times this happened, it was really intended to be comparison operation."

Why not FIX THE PROBLEM?

Instead of = for assignment and == for equality test, why not use := for assignment and = (or even ==) for equality?

If you want to make it harder for the programmer to mistake assignment for equality, then make it harder.

At the same time, if you REALLY wanted to fix the problem, you would remove the C crock that claimed booleans were just integers with predefined symbolic sugar names. Make them a different type altogether. Then, instead of saying

you force the programmer to write:

The fact is that assignment-as-an-operator is a very useful construct. We didn't eliminate razor blades because some people cut themselves. Instead, King Gillette invented the safety razor.

John R. Strohm's user avatar

  • 2 (1) := for assignment and = for equality might fix this problem, but at the cost of alienating every programmer who didn't grow up using a small set of non-mainstream languages. (2) Types other than bools being allows in conditions isn't always due to mixing up bools and integers, it's sufficient to give a true/false interpretation to other types. Newer language that aren't afraid to deviate from C have done so for many types other than integers (e.g. Python considers empty collections false). –  user7043 Commented Feb 13, 2014 at 13:38
  • 1 And regarding razor blades: Those serve a use case that necessitates sharpness. On the other hand, I'm not convinced programming well requires assigning to variables in the middle of an expression evaluation. If there was a simple, low-tech, safe and cost efficient way to make body hair disappear without sharp edges, I'm sure razor blades would have been displaced or at least made much more rare. –  user7043 Commented Feb 13, 2014 at 13:40
  • 1 @delnan: A wise man once said "Make it as simple as possible, but no simpler." If your objective is to eliminate the vast majority of a=b vs. a==b errors, restricting the domain of conditional tests to booleans and eliminating the default type conversion rules for <other>->boolean gets you just about all the way there. At that point, if(a=b){} is only syntactically legal if a and b are both boolean and a is a legal lvalue. –  John R. Strohm Commented Feb 13, 2014 at 15:07
  • Making assignment a statement is at least as simple as -- arguably even simpler than -- the changes you propose, and achieves at least as much -- arguably even more (doesn't even permit if (a = b) for lvalue a, boolean a, b). In a language without static typing, it also gives much better error messages (at parse time vs. run time). In addition, preventing "a=b vs. a==b errors" may not be the only relevant objective. For example, I'd also like to permit code like if items: to mean if len(items) != 0 , and that I'd have to give up to restrict conditions to booleans. –  user7043 Commented Feb 13, 2014 at 15:14
  • 1 @delnan Pascal is a non-mainstream language? Millions of people learned programming using Pascal (and/or Modula, which derives from Pascal). And Delphi is still commonly used in many countries (maybe not so much in yours). –  jwenting Commented Feb 14, 2014 at 9:39

To actually answer the question, yes there are numerous uses of this although they are slightly niche.

For example in Java:

The alternative without using the embedded assignment requires the ob defined outside the scope of the loop and two separate code locations that call x.next().

It's already been mentioned that you can assign multiple variables in one step.

This sort of thing is the most common use, but creative programmers will always come up with more.

Tim B's user avatar

  • Would that while loop condition deallocate and create a new ob object with every loop? –  user3932000 Commented May 3, 2017 at 22:33
  • @user3932000 In that case probably not, usually x.next() is iterating over something. It is certainly possible that it could though. –  Tim B Commented May 4, 2017 at 8:18
  • I can't get the above to compile unless I declare the variable beforehand and remove the declaration from inside. It says Object cannot be resolved to a variable. –  William Jarvis Commented Apr 15, 2021 at 16:42

Since you get to make up all the rules, why now allow assignment to turn a value, and simply not allow assignments inside conditional steps? This gives you the syntactic sugar to make initializations easy, while still preventing a common coding mistake.

In other words, make this legal:

But make this illegal:

Bryan Oakley's user avatar

  • 2 That seems like a rather ad-hoc rule. Making assignment a statement and extending it to allow a = b = c seems more orthogonal, and easier to implement too. These two approach disagree about assignment in expressions ( a + (b = c) ), but you haven't taken sides on those so I assume they don't matter. –  user7043 Commented Feb 13, 2014 at 13:01
  • "easy to implement" shouldn't be much of a consideration. You are defining a user interface -- put the needs of the users first. You simply need to ask yourself whether this behavior helps or hinders the user. –  Bryan Oakley Commented Feb 13, 2014 at 13:05
  • if you disallow implicit conversion to bool then you don't have to worry about assignment in conditions –  ratchet freak Commented Feb 13, 2014 at 13:08
  • Easier to implement was only one of my arguments. What about the rest? From the UI angle, I might add that IMHO incoherent design and ad-hoc exceptions generally hinders the user in grokking and internalising the rules. –  user7043 Commented Feb 13, 2014 at 13:10
  • @ratchetfreak you could still have an issue with assigning actual bools –  jk. Commented Feb 13, 2014 at 13:25

By the sounds of it, you are on the path of creating a fairly strict language.

With that in mind, forcing people to write:

instead of:

might seem an improvement to prevent people from doing:

when they meant to do:

but in the end, this kind of errors are easy to detect and warn about whether or not they are legal code.

However, there are situations where doing:

does not mean that

will be true.

If c is actually a function c() then it could return different results each time it is called. (it might also be computationally expensive too...)

Likewise if c is a pointer to memory mapped hardware, then

are both likely to be different, and also may also have electronic effects on the hardware on each read.

There are plenty of other permutations with hardware where you need to be precise about what memory addresses are read from, written to and under specific timing constraints, where doing multiple assignments on the same line is quick, simple and obvious, without the timing risks that temporary variables introduce

Michael Shaw's user avatar

  • 4 The equivalent to a = b = c isn't a = c; b = c , it's b = c; a = b . This avoids duplication of side effects and also keeps the modification of a and b in the same order. Also, all these hardware-related arguments are kind of stupid: Most languages are not system languages and are neither designed to solve these problems nor are they being used in situations where these problems occur. This goes doubly for a language that attempts to displace JavaScript and/or PHP. –  user7043 Commented Feb 13, 2014 at 13:04
  • delnan, the issue wasn't are these contrived examples, they are. The point still stands that they show the kinds of places where writing a=b=c is common, and in the hardware case, considered good practice, as the OP asked for. I'm sure they will be able to consider their relevance to their expected environment –  Michael Shaw Commented Feb 13, 2014 at 13:51
  • Looking back, my problem with this answer is not primarily that it focuses on system programming use cases (though that would be bad enough, the way it's written), but that it rests on assuming an incorrect rewriting. The examples aren't examples of places where a=b=c is common/useful, they are examples of places where order and number of side effects must be taken care of. That is entirely independent. Rewrite the chained assignment correctly and both variants are equally correct. –  user7043 Commented Feb 13, 2014 at 13:58
  • @delnan: The rvalue is converted to the type of b in one temp, and that is converted to the type of a in another temp. The relative timing of when those values are actually stored is unspecified. From a language-design perspective, I would think it reasonable to require that all lvalues in a multiple-assignment statement have matching type, and possibly to require as well that none of them be volatile. –  supercat Commented Feb 13, 2014 at 19:17

The greatest benefit to my mind of having assignment be an expression is that it allows your grammar to be simpler if one of your goals is that "everything is an expression"--a goal of LISP in particular.

Python does not have this; it has expressions and statements, assignment being a statement. But because Python defines a lambda form as being a single parameterized expression , that means you can't assign variables inside a lambda. This is inconvenient at times, but not a critical issue, and it's about the only downside in my experience to having assignment be a statement in Python.

One way to allow assignment, or rather the effect of assignment, to be an expression without introducing the potential for if(x=1) accidents that C has is to use a LISP-like let construct, such as (let ((x 2) (y 3)) (+ x y)) which might in your language evaluate as 5 . Using let this way need not technically be assignment at all in your language, if you define let as creating a lexical scope. Defined that way, a let construct could be compiled the same way as constructing and calling a nested closure function with arguments.

On the other hand, if you are simply concerned with the if(x=1) case, but want assignment to be an expression as in C, maybe just choosing different tokens will suffice. Assignment: x := 1 or x <- 1 . Comparison: x == 1 . Syntax error: x = 1 .

wberry's user avatar

  • 1 let differs from assignment in more ways than technically introducing a new variable in a new scope. For starters, it has no effect on code outside the let 's body, and therefore requires nesting all code (what should use the variable) further, a significant downside in assignment-heavy code. If one was to go down that route, set! would be the better Lisp analogue - completely unlike comparison, yet not requiring nesting or a new scope. –  user7043 Commented Feb 13, 2014 at 21:36
  • @delnan: I'd like to see a combination declare-and-assign syntax which would prohibit reassignment but would allow redeclaration, subject to the rules that (1) redeclaration would only be legal for declare-and-assign identifiers, and (2) redeclaration would "undeclare" a variable in all enclosing scopes. Thus, the value of any valid identifier would be whatever was assigned in the previous declaration of that name. That would seem a little nicer than having to add scoping blocks for variables that are only used for a few lines, or having to formulate new names for each temp variable. –  supercat Commented Feb 14, 2014 at 3:08

Indeed. This is nothing new, all the safe subsets of the C language have already made this conclusion.

MISRA-C, CERT-C and so on all ban assignment inside conditions, simply because it is dangerous.

There exists no case where code relying on assignment inside conditions cannot be rewritten.

Furthermore, such standards also warns against writing code that relies on the order of evaluation. Multiple assignments on one single row x=y=z; is such a case. If a row with multiple assignments contains side effects (calling functions, accessing volatile variables etc), you cannot know which side effect that will occur first.

There are no sequence points between the evaluation of the operands. So we cannot know whether the subexpression y gets evaluated before or after z : it is unspecified behavior in C. Thus such code is potentially unreliable, non-portable and non-conformant to the mentioned safe subsets of C.

The solution would have been to replace the code with y=z; x=y; . This adds a sequence point and guarantees the order of evaluation.

So based on all the problems this caused in C, any modern language would do well to both ban assignment inside conditions, as well as multiple assignments on one single row.

Not the answer you're looking for? Browse other questions tagged language-agnostic syntax operators or ask your own question .

  • The Overflow Blog
  • Unpacking the 2024 Developer Survey results
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Introducing an accessibility dashboard and some upcoming changes to display...

Hot Network Questions

  • If it's true that a reservation fee for a cruise ship is non-refundable, then what happens if somebody cancels?
  • Can the Bible be the word of God, when there are multiple versions of it?
  • Why do most published papers hit the maximum page limit exactly?
  • If pressure is caused by the weight of water above you, why is pressure said to act in all direction, not just down?
  • How important is a "no reflection" strategy for 1 Hz systems?
  • What is “were’t”?
  • Should I include MA theses in my phd literature review?
  • Refereeing papers by people you are very close to
  • Is Marisa Tomei in the film the Toxic Avenger?
  • Search values by priority in stream
  • How to get this fencing wire at a [somewhat] equal tension
  • Netgate 6100 Will Not Acknowledge Lastest Versions of pfSense (When Checking For Updates)
  • Tefilin on Tisha Be'Av according the Chida
  • What happens if your child sells your car?
  • What happened to MOSBD?
  • Do academic researchers generally not worry about their work infringing on patents? Have there been cases where they wish they had?
  • Why is the completely dark disk of the Moon visible on a new moon if the lunar orbit is at an angle to the Earth’s?
  • What does "No camping 10-21" mean?
  • Does wisdom come with age?
  • Why didn't my TX get rejected?
  • Reportedly there are German-made infantry fighting vehicles in Russia's Kursk region. Has this provoked any backlash in Germany?
  • Reduce spacing between letters in equations
  • Where did it come from: an etymology puzzle
  • Combinatorial type construction of the Free Operad

assignment statement return

cppreference.com

Assignment operators.

(C++20)
(C++20)
(C++11)
(C++20)
(C++17)
(C++11)
(C++11)
General topics
(C++11)
-
-expression
block


/
(C++11)
(C++11)
(C++11)
(C++20)
(C++20)
(C++11)

expression
pointer
specifier

specifier (C++11)
specifier (C++11)
(C++11)

(C++11)
(C++11)
(C++11)
General
(C++11)
(C++26)

(C++11)
(C++11)
-expression
-expression
-expression
(C++11)
(C++11)
(C++17)
(C++20)
    

Assignment operators modify the value of the object.

Operator name  Syntax  Prototype examples (for class T)
Inside class definition Outside class definition
simple assignment Yes T& T::operator =(const T2& b);
addition assignment Yes T& T::operator +=(const T2& b); T& operator +=(T& a, const T2& b);
subtraction assignment Yes T& T::operator -=(const T2& b); T& operator -=(T& a, const T2& b);
multiplication assignment Yes T& T::operator *=(const T2& b); T& operator *=(T& a, const T2& b);
division assignment Yes T& T::operator /=(const T2& b); T& operator /=(T& a, const T2& b);
remainder assignment Yes T& T::operator %=(const T2& b); T& operator %=(T& a, const T2& b);
bitwise AND assignment Yes T& T::operator &=(const T2& b); T& operator &=(T& a, const T2& b);
bitwise OR assignment Yes T& T::operator |=(const T2& b); T& operator |=(T& a, const T2& b);
bitwise XOR assignment Yes T& T::operator ^=(const T2& b); T& operator ^=(T& a, const T2& b);
bitwise left shift assignment Yes T& T::operator <<=(const T2& b); T& operator <<=(T& a, const T2& b);
bitwise right shift assignment Yes T& T::operator >>=(const T2& b); T& operator >>=(T& a, const T2& b);

this, and most also return *this so that the user-defined operators can be used in the same manner as the built-ins. However, in a user-defined operator overload, any type can be used as return type (including void). can be any type including .
Definitions Assignment operator syntax Built-in simple assignment operator Assignment from an expression Assignment from a non-expression initializer clause Built-in compound assignment operator Example Defect reports See also

[ edit ] Definitions

Copy assignment replaces the contents of the object a with a copy of the contents of b ( b is not modified). For class types, this is performed in a special member function, described in copy assignment operator .

replaces the contents of the object a with the contents of b, avoiding copying if possible (b may be modified). For class types, this is performed in a special member function, described in .

(since C++11)

For non-class types, copy and move assignment are indistinguishable and are referred to as direct assignment .

Compound assignment replace the contents of the object a with the result of a binary operation between the previous value of a and the value of b .

[ edit ] Assignment operator syntax

The assignment expressions have the form

target-expr new-value (1)
target-expr op new-value (2)
target-expr - the expression to be assigned to
op - one of *=, /= %=, += -=, <<=, >>=, &=, ^=, |=
new-value - the expression (until C++11) (since C++11) to assign to the target
  • ↑ target-expr must have higher precedence than an assignment expression.
  • ↑ new-value cannot be a comma expression, because its precedence is lower.

If new-value is not an expression, the assignment expression will never match an overloaded compound assignment operator.

(since C++11)

[ edit ] Built-in simple assignment operator

For the built-in simple assignment, the object referred to by target-expr is modified by replacing its value with the result of new-value . target-expr must be a modifiable lvalue.

The result of a built-in simple assignment is an lvalue of the type of target-expr , referring to target-expr . If target-expr is a bit-field , the result is also a bit-field.

[ edit ] Assignment from an expression

If new-value is an expression, it is implicitly converted to the cv-unqualified type of target-expr . When target-expr is a bit-field that cannot represent the value of the expression, the resulting value of the bit-field is implementation-defined.

If target-expr and new-value identify overlapping objects, the behavior is undefined (unless the overlap is exact and the type is the same).

If the type of target-expr is volatile-qualified, the assignment is deprecated, unless the (possibly parenthesized) assignment expression is a or an .

(since C++20)

new-value is only allowed not to be an expression in following situations:

is of a , and new-value is empty or has only one element. In this case, given an invented variable t declared and initialized as T t = new-value , the meaning of x = new-value  is x = t. is of class type. In this case, new-value is passed as the argument to the assignment operator function selected by .   <double> z; z = {1, 2}; // meaning z.operator=({1, 2}) z += {1, 2}; // meaning z.operator+=({1, 2})   int a, b; a = b = {1}; // meaning a = b = 1; a = {1} = b; // syntax error
(since C++11)

In overload resolution against user-defined operators , for every type T , the following function signatures participate in overload resolution:

& operator=(T*&, T*);
volatile & operator=(T*volatile &, T*);

For every enumeration or pointer to member type T , optionally volatile-qualified, the following function signature participates in overload resolution:

operator=(T&, T);

For every pair A1 and A2 , where A1 is an arithmetic type (optionally volatile-qualified) and A2 is a promoted arithmetic type, the following function signature participates in overload resolution:

operator=(A1&, A2);

[ edit ] Built-in compound assignment operator

The behavior of every built-in compound-assignment expression target-expr   op   =   new-value is exactly the same as the behavior of the expression target-expr   =   target-expr   op   new-value , except that target-expr is evaluated only once.

The requirements on target-expr and new-value of built-in simple assignment operators also apply. Furthermore:

  • For + = and - = , the type of target-expr must be an arithmetic type or a pointer to a (possibly cv-qualified) completely-defined object type .
  • For all other compound assignment operators, the type of target-expr must be an arithmetic type.

In overload resolution against user-defined operators , for every pair A1 and A2 , where A1 is an arithmetic type (optionally volatile-qualified) and A2 is a promoted arithmetic type, the following function signatures participate in overload resolution:

operator*=(A1&, A2);
operator/=(A1&, A2);
operator+=(A1&, A2);
operator-=(A1&, A2);

For every pair I1 and I2 , where I1 is an integral type (optionally volatile-qualified) and I2 is a promoted integral type, the following function signatures participate in overload resolution:

operator%=(I1&, I2);
operator<<=(I1&, I2);
operator>>=(I1&, I2);
operator&=(I1&, I2);
operator^=(I1&, I2);
operator|=(I1&, I2);

For every optionally cv-qualified object type T , the following function signatures participate in overload resolution:

& operator+=(T*&, );
& operator-=(T*&, );
volatile & operator+=(T*volatile &, );
volatile & operator-=(T*volatile &, );

[ edit ] Example

Possible output:

[ edit ] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
C++11 for assignments to class type objects, the right operand
could be an initializer list only when the assignment
is defined by a user-defined assignment operator
removed user-defined
assignment constraint
C++11 E1 = {E2} was equivalent to E1 = T(E2)
( is the type of ), this introduced a C-style cast
it is equivalent
to E1 = T{E2}
C++20 compound assignment operators for volatile
-qualified types were inconsistently deprecated
none of them
is deprecated
C++11 an assignment from a non-expression initializer clause
to a scalar value would perform direct-list-initialization
performs copy-list-
initialization instead
C++20 bitwise compound assignment operators for volatile types
were deprecated while being useful for some platforms
they are not
deprecated

[ edit ] See also

Operator precedence

Operator overloading

Common operators

a = b
a += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b

++a
--a
a++
a--

+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

!a
a && b
a || b

a == b
a != b
a < b
a > b
a <= b
a >= b
a <=> b

a[...]
*a
&a
a->b
a.b
a->*b
a.*b

function call
a(...)
comma
a, b
conditional
a ? b : c
Special operators

converts one type to another related type
converts within inheritance hierarchies
adds or removes -qualifiers
converts type to unrelated type
converts one type to another by a mix of , , and
creates objects with dynamic storage duration
destructs objects previously created by the new expression and releases obtained memory area
queries the size of a type
queries the size of a (since C++11)
queries the type information of a type
checks if an expression can throw an exception (since C++11)
queries alignment requirements of a type (since C++11)

for Assignment operators
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 25 January 2024, at 23:41.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Assignment operators

  • 8 contributors

expression assignment-operator expression

assignment-operator : one of   =   *=   /=   %=   +=   -=   <<=   >>=   &=   ^=   |=

Assignment operators store a value in the object specified by the left operand. There are two kinds of assignment operations:

simple assignment , in which the value of the second operand is stored in the object specified by the first operand.

compound assignment , in which an arithmetic, shift, or bitwise operation is performed before storing the result.

All assignment operators in the following table except the = operator are compound assignment operators.

Assignment operators table

Operator Meaning
Store the value of the second operand in the object specified by the first operand (simple assignment).
Multiply the value of the first operand by the value of the second operand; store the result in the object specified by the first operand.
Divide the value of the first operand by the value of the second operand; store the result in the object specified by the first operand.
Take modulus of the first operand specified by the value of the second operand; store the result in the object specified by the first operand.
Add the value of the second operand to the value of the first operand; store the result in the object specified by the first operand.
Subtract the value of the second operand from the value of the first operand; store the result in the object specified by the first operand.
Shift the value of the first operand left the number of bits specified by the value of the second operand; store the result in the object specified by the first operand.
Shift the value of the first operand right the number of bits specified by the value of the second operand; store the result in the object specified by the first operand.
Obtain the bitwise AND of the first and second operands; store the result in the object specified by the first operand.
Obtain the bitwise exclusive OR of the first and second operands; store the result in the object specified by the first operand.
Obtain the bitwise inclusive OR of the first and second operands; store the result in the object specified by the first operand.

Operator keywords

Three of the compound assignment operators have keyword equivalents. They are:

Operator Equivalent

C++ specifies these operator keywords as alternative spellings for the compound assignment operators. In C, the alternative spellings are provided as macros in the <iso646.h> header. In C++, the alternative spellings are keywords; use of <iso646.h> or the C++ equivalent <ciso646> is deprecated. In Microsoft C++, the /permissive- or /Za compiler option is required to enable the alternative spelling.

Simple assignment

The simple assignment operator ( = ) causes the value of the second operand to be stored in the object specified by the first operand. If both objects are of arithmetic types, the right operand is converted to the type of the left, before storing the value.

Objects of const and volatile types can be assigned to l-values of types that are only volatile , or that aren't const or volatile .

Assignment to objects of class type ( struct , union , and class types) is performed by a function named operator= . The default behavior of this operator function is to perform a member-wise copy assignment of the object's non-static data members and direct base classes; however, this behavior can be modified using overloaded operators. For more information, see Operator overloading . Class types can also have copy assignment and move assignment operators. For more information, see Copy constructors and copy assignment operators and Move constructors and move assignment operators .

An object of any unambiguously derived class from a given base class can be assigned to an object of the base class. The reverse isn't true because there's an implicit conversion from derived class to base class, but not from base class to derived class. For example:

Assignments to reference types behave as if the assignment were being made to the object to which the reference points.

For class-type objects, assignment is different from initialization. To illustrate how different assignment and initialization can be, consider the code

The preceding code shows an initializer; it calls the constructor for UserType2 that takes an argument of type UserType1 . Given the code

the assignment statement

can have one of the following effects:

Call the function operator= for UserType2 , provided operator= is provided with a UserType1 argument.

Call the explicit conversion function UserType1::operator UserType2 , if such a function exists.

Call a constructor UserType2::UserType2 , provided such a constructor exists, that takes a UserType1 argument and copies the result.

Compound assignment

The compound assignment operators are shown in the Assignment operators table . These operators have the form e1 op = e2 , where e1 is a non- const modifiable l-value and e2 is:

an arithmetic type

a pointer, if op is + or -

a type for which there exists a matching operator *op*= overload for the type of e1

The built-in e1 op = e2 form behaves as e1 = e1 op e2 , but e1 is evaluated only once.

Compound assignment to an enumerated type generates an error message. If the left operand is of a pointer type, the right operand must be of a pointer type, or it must be a constant expression that evaluates to 0. When the left operand is of an integral type, the right operand must not be of a pointer type.

Result of built-in assignment operators

The built-in assignment operators return the value of the object specified by the left operand after the assignment (and the arithmetic/logical operation in the case of compound assignment operators). The resultant type is the type of the left operand. The result of an assignment expression is always an l-value. These operators have right-to-left associativity. The left operand must be a modifiable l-value.

In ANSI C, the result of an assignment expression isn't an l-value. That means the legal C++ expression (a += b) += c isn't allowed in C.

Expressions with binary operators C++ built-in operators, precedence, and associativity C assignment operators

Was this page helpful?

Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback .

Submit and view feedback for

Additional resources

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

clear sunny desert yellow sand with celestial snow bridge

1.7 Java | Assignment Statements & Expressions

An assignment statement designates a value for a variable. An assignment statement can be used as an expression in Java.

After a variable is declared, you can assign a value to it by using an assignment statement . In Java, the equal sign = is used as the assignment operator . The syntax for assignment statements is as follows:

An expression represents a computation involving values, variables, and operators that, when taking them together, evaluates to a value. For example, consider the following code:

You can use a variable in an expression. A variable can also be used on both sides of the =  operator. For example:

In the above assignment statement, the result of x + 1  is assigned to the variable x . Let’s say that x is 1 before the statement is executed, and so becomes 2 after the statement execution.

To assign a value to a variable, you must place the variable name to the left of the assignment operator. Thus the following statement is wrong:

Note that the math equation  x = 2 * x + 1  ≠ the Java expression x = 2 * x + 1

Java Assignment Statement vs Assignment Expression

Which is equivalent to:

And this statement

is equivalent to:

Note: The data type of a variable on the left must be compatible with the data type of a value on the right. For example, int x = 1.0 would be illegal, because the data type of x is int (integer) and does not accept the double value 1.0 without Type Casting .

◄◄◄BACK | NEXT►►►

What's Your Opinion? Cancel reply

Enhance your Brain

Subscribe to Receive Free Bio Hacking, Nootropic, and Health Information

HTML for Simple Website Customization My Personal Web Customization Personal Insights

DISCLAIMER | Sitemap | ◘

SponserImageUCD

HTML for Simple Website Customization My Personal Web Customization Personal Insights SEO Checklist Publishing Checklist My Tools

Top Posts & Pages

1. VbScript | Message Box

  • Assignment Statement

An Assignment statement is a statement that is used to set a value to the variable name in a program .

Assignment statement allows a variable to hold different types of values during its program lifespan. Another way of understanding an assignment statement is, it stores a value in the memory location which is denoted by a variable name.

Assignment Statement Method

The symbol used in an assignment statement is called as an operator . The symbol is ‘=’ .

Note: The Assignment Operator should never be used for Equality purpose which is double equal sign ‘==’.

The Basic Syntax of Assignment Statement in a programming language is :

variable = expression ;

variable = variable name

expression = it could be either a direct value or a math expression/formula or a function call

Few programming languages such as Java, C, C++ require data type to be specified for the variable, so that it is easy to allocate memory space and store those values during program execution.

data_type variable_name = value ;

In the above-given examples, Variable ‘a’ is assigned a value in the same statement as per its defined data type. A data type is only declared for Variable ‘b’. In the 3 rd line of code, Variable ‘a’ is reassigned the value 25. The 4 th line of code assigns the value for Variable ‘b’.

Assignment Statement Forms

This is one of the most common forms of Assignment Statements. Here the Variable name is defined, initialized, and assigned a value in the same statement. This form is generally used when we want to use the Variable quite a few times and we do not want to change its value very frequently.

Tuple Assignment

Generally, we use this form when we want to define and assign values for more than 1 variable at the same time. This saves time and is an easy method. Note that here every individual variable has a different value assigned to it.

(Code In Python)

Sequence Assignment

(Code in Python)

Multiple-target Assignment or Chain Assignment

In this format, a single value is assigned to two or more variables.

Augmented Assignment

In this format, we use the combination of mathematical expressions and values for the Variable. Other augmented Assignment forms are: &=, -=, **=, etc.

Browse more Topics Under Data Types, Variables and Constants

  • Concept of Data types
  • Built-in Data Types
  • Constants in Programing Language 
  • Access Modifier
  • Variables of Built-in-Datatypes
  • Declaration/Initialization of Variables
  • Type Modifier

Few Rules for Assignment Statement

Few Rules to be followed while writing the Assignment Statements are:

  • Variable names must begin with a letter, underscore, non-number character. Each language has its own conventions.
  • The Data type defined and the variable value must match.
  • A variable name once defined can only be used once in the program. You cannot define it again to store other types of value.
  • If you assign a new value to an existing variable, it will overwrite the previous value and assign the new value.

FAQs on Assignment Statement

Q1. Which of the following shows the syntax of an  assignment statement ?

  • variablename = expression ;
  • expression = variable ;
  • datatype = variablename ;
  • expression = datatype variable ;

Answer – Option A.

Q2. What is an expression ?

  • Same as statement
  • List of statements that make up a program
  • Combination of literals, operators, variables, math formulas used to calculate a value
  • Numbers expressed in digits

Answer – Option C.

Q3. What are the two steps that take place when an  assignment statement  is executed?

  • Evaluate the expression, store the value in the variable
  • Reserve memory, fill it with value
  • Evaluate variable, store the result
  • Store the value in the variable, evaluate the expression.

Customize your course in 30 seconds

Which class are you in.

tutor

Data Types, Variables and Constants

  • Variables in Programming Language
  • Concept of Data Types
  • Declaration of Variables
  • Type Modifiers
  • Access Modifiers
  • Constants in Programming Language

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Download the App

Google Play

  • C Data Types
  • C Operators
  • C Input and Output
  • C Control Flow
  • C Functions
  • C Preprocessors
  • C File Handling
  • C Cheatsheet
  • C Interview Questions

Assignment Operators in C

assignment statement return

Assignment operators are used for assigning value to a variable. The left side operand of the assignment operator is a variable and right side operand of the assignment operator is a value. The value on the right side must be of the same data-type of the variable on the left side otherwise the compiler will raise an error.

Different types of assignment operators are shown below:

1. “=”: This is the simplest assignment operator. This operator is used to assign the value on the right to the variable on the left. Example:

2. “+=” : This operator is combination of ‘+’ and ‘=’ operators. This operator first adds the current value of the variable on left to the value on the right and then assigns the result to the variable on the left. Example:

If initially value stored in a is 5. Then (a += 6) = 11.

3. “-=” This operator is combination of ‘-‘ and ‘=’ operators. This operator first subtracts the value on the right from the current value of the variable on left and then assigns the result to the variable on the left. Example:

If initially value stored in a is 8. Then (a -= 6) = 2.

4. “*=” This operator is combination of ‘*’ and ‘=’ operators. This operator first multiplies the current value of the variable on left to the value on the right and then assigns the result to the variable on the left. Example:

If initially value stored in a is 5. Then (a *= 6) = 30.

5. “/=” This operator is combination of ‘/’ and ‘=’ operators. This operator first divides the current value of the variable on left by the value on the right and then assigns the result to the variable on the left. Example:

If initially value stored in a is 6. Then (a /= 2) = 3.

Below example illustrates the various Assignment Operators:

Please Login to comment...

Similar reads.

  • C-Operators
  • cpp-operator

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

  • Skip to main content
  • Skip to search
  • Skip to select language
  • Sign up for free

Assignment (=)

The assignment ( = ) operator is used to assign a value to a variable or property. The assignment expression itself has a value, which is the assigned value. This allows multiple assignments to be chained in order to assign a single value to multiple variables.

A valid assignment target, including an identifier or a property accessor . It can also be a destructuring assignment pattern .

An expression specifying the value to be assigned to x .

Return value

The value of y .

Thrown in strict mode if assigning to an identifier that is not declared in the scope.

Thrown in strict mode if assigning to a property that is not modifiable .

Description

The assignment operator is completely different from the equals ( = ) sign used as syntactic separators in other locations, which include:

  • Initializers of var , let , and const declarations
  • Default values of destructuring
  • Default parameters
  • Initializers of class fields

All these places accept an assignment expression on the right-hand side of the = , so if you have multiple equals signs chained together:

This is equivalent to:

Which means y must be a pre-existing variable, and x is a newly declared const variable. y is assigned the value 5 , and x is initialized with the value of the y = 5 expression, which is also 5 . If y is not a pre-existing variable, a global variable y is implicitly created in non-strict mode , or a ReferenceError is thrown in strict mode. To declare two variables within the same declaration, use:

Simple assignment and chaining

Value of assignment expressions.

The assignment expression itself evaluates to the value of the right-hand side, so you can log the value and assign to a variable at the same time.

Unqualified identifier assignment

The global object sits at the top of the scope chain. When attempting to resolve a name to a value, the scope chain is searched. This means that properties on the global object are conveniently visible from every scope, without having to qualify the names with globalThis. or window. or global. .

Because the global object has a String property ( Object.hasOwn(globalThis, "String") ), you can use the following code:

So the global object will ultimately be searched for unqualified identifiers. You don't have to type globalThis.String ; you can just type the unqualified String . To make this feature more conceptually consistent, assignment to unqualified identifiers will assume you want to create a property with that name on the global object (with globalThis. omitted), if there is no variable of the same name declared in the scope chain.

In strict mode , assignment to an unqualified identifier in strict mode will result in a ReferenceError , to avoid the accidental creation of properties on the global object.

Note that the implication of the above is that, contrary to popular misinformation, JavaScript does not have implicit or undeclared variables. It just conflates the global object with the global scope and allows omitting the global object qualifier during property creation.

Assignment with destructuring

The left-hand side of can also be an assignment pattern. This allows assigning to multiple variables at once.

For more information, see Destructuring assignment .

Specifications

Specification

Browser compatibility

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

  • Assignment operators in the JS guide
  • Destructuring assignment

The Python return Statement: Usage and Best Practices

The Python return Statement: Usage and Best Practices

Table of Contents

Getting Started With Python Functions

Explicit return statements, implicit return statements, returning vs printing, returning multiple values, returning none explicitly, remembering the return value, avoiding complex expressions, returning values vs modifying globals, using return with conditionals, returning true or false, short-circuiting loops, recognizing dead code, returning multiple named-objects, returning functions: closures, taking and returning functions: decorators, returning user-defined objects: the factory pattern, using return in try … finally blocks, using return in generator functions.

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: Using the Python return Statement Effectively

The Python return statement is a special statement that you can use inside a function or method to send the function’s result back to the caller. A return statement consists of the return keyword followed by an optional return value . The return value of a Python function can be any Python object, and you can use them to perform further computation in your programs.

Using the return statement effectively is a core skill if you want to code custom functions that are Pythonic and robust.

In this tutorial, you’ll learn that:

  • You use return to send objects from your functions back to the caller code.
  • You can use return to return one single value or multiple values separated by commas.
  • You should try to keep your code readable and maintainable by avoiding complex return statements.

With this knowledge, you’ll be able to write more readable, maintainable, and concise functions in Python. If you’re totally new to Python functions, then you can check out Defining Your Own Python Function before diving into this tutorial.

Free Bonus: 5 Thoughts On Python Mastery , a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.

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

Interactive Quiz

In this quiz, you can practice your understanding of how to use the Python return statement when writing functions. Additionally, you'll cover some good programming practices related to the use of return. With this knowledge, you'll be able to write readable, robust, and maintainable functions in Python.

Most programming languages allow you to assign a name to a code block that performs a concrete computation. These named code blocks can be reused quickly because you can use their name to call them from different places in your code.

Programmers call these named code blocks subroutines , routines , procedures , or functions depending on the language they use. In some languages, there’s a clear difference between a routine or procedure and a function.

Sometimes that difference is so strong that you need to use a specific keyword to define a procedure or subroutine and another keyword to define a function. For example the Visual Basic programming language uses Sub and Function to differentiate between the two.

In general, a procedure is a named code block that performs a set of actions without computing a final value or result. On the other hand, a function is a named code block that performs some actions with the purpose of computing a final value or result, which is then sent back to the caller code. Both procedures and functions can act upon a set of input values , commonly known as arguments .

In Python, these kinds of named code blocks are known as functions because they always send a value back to the caller. The Python documentation defines a function as follows:

A series of statements which returns some value to a caller. It can also be passed zero or more arguments which may be used in the execution of the body. ( Source )

Even though the official documentation states that a function “returns some value to the caller,” you’ll soon see that functions can return any Python object to the caller code.

In general, a function takes arguments (if any), performs some operations, and returns a value (or object). The value that a function returns to the caller is generally known as the function’s return value . All Python functions have a return value, either explicit or implicit. You’ll cover the difference between explicit and implicit return values later in this tutorial.

To write a Python function, you need a header that starts with the def keyword , followed by the name of the function, an optional list of comma-separated arguments inside a required pair of parentheses, and a final colon.

The second component of a function is its code block , or body . Python defines code blocks using indentation instead of brackets, begin and end keywords, and so on. So, to define a function in Python you can use the following syntax:

When you’re coding a Python function, you need to define a header with the def keyword, the name of the function, and a list of arguments in parentheses. Note that the list of arguments is optional, but the parentheses are syntactically required. Then you need to define the function’s code block, which will begin one level of indentation to the right.

In the above example, you use a pass statement . This kind of statement is useful when you need a placeholder statement in your code to make it syntactically correct, but you don’t need to perform any action. pass statements are also known as the null operation because they don’t perform any action.

Note: The full syntax to define functions and their arguments is beyond the scope of this tutorial. For an in-depth resource on this topic, check out Defining Your Own Python Function .

To use a function, you need to call it. A function call consists of the function’s name followed by the function’s arguments in parentheses:

You’ll need to pass arguments to a function call only if the function requires them. The parentheses, on the other hand, are always required in a function call. If you forget them, then you won’t be calling the function but referencing it as a function object.

To make your functions return a value, you need to use the Python return statement . That’s what you’ll cover from this point on.

Understanding the Python return Statement

The Python return statement is a special statement that you can use inside a function or method to send the function’s result back to the caller. A return statement consists of the return keyword followed by an optional return value .

The return value of a Python function can be any Python object. Everything in Python is an object. So, your functions can return numeric values ( int , float , and complex values), collections and sequences of objects ( list , tuple , dictionary , or set objects), user-defined objects, classes, functions, and even modules or packages .

You can omit the return value of a function and use a bare return without a return value. You can also omit the entire return statement. In both cases, the return value will be None .

In the next two sections, you’ll cover the basics of how the return statement works and how you can use it to return the function’s result back to the caller code.

An explicit return statement immediately terminates a function execution and sends the return value back to the caller code. To add an explicit return statement to a Python function, you need to use return followed by an optional return value:

When you define return_42() , you add an explicit return statement ( return 42 ) at the end of the function’s code block. 42 is the explicit return value of return_42() . This means that any time you call return_42() , the function will send 42 back to the caller.

Note: You can use explicit return statements with or without a return value. If you build a return statement without specifying a return value, then you’ll be implicitly returning None .

If you define a function with an explicit return statement that has an explicit return value, then you can use that return value in any expression:

Since return_42() returns a numeric value, you can use that value in a math expression or any other kind of expression in which the value has a logical or coherent meaning. This is how a caller code can take advantage of a function’s return value.

Note that you can use a return statement only inside a function or method definition. If you use it anywhere else, then you’ll get a SyntaxError :

When you use return outside a function or method, you get a SyntaxError telling you that the statement can’t be used outside a function.

Note: Regular methods, class methods, and static methods are just functions within the context of Python classes . So, all the return statement concepts that you’ll cover apply to them as well.

You can use any Python object as a return value. Since everything in Python is an object, you can return strings , lists, tuples, dictionaries, functions, classes, instances , user-defined objects, and even modules or packages.

For example, say you need to write a function that takes a list of integers and returns a list containing only the even numbers in the original list. Here’s a way of coding this function:

get_even() uses a list comprehension to create a list that filters out the odd numbers in the original numbers . Then the function returns the resulting list, which contains only even numbers.

A common practice is to use the result of an expression as a return value in a return statement. To apply this idea, you can rewrite get_even() as follows:

The list comprehension gets evaluated and then the function returns with the resulting list. Note that you can only use expressions in a return statement. Expressions are different from statements like conditionals or loops .

Note: Even though list comprehensions are built using for and (optionally) if keywords, they’re considered expressions rather than statements. That’s why you can use them in a return statement.

For a further example, say you need to calculate the mean of a sample of numeric values. To do that, you need to divide the sum of the values by the number of values. Here’s an example that uses the built-in functions sum() and len() :

In mean() , you don’t use a local variable to store the result of the calculation. Instead, you use the expression directly as a return value. Python first evaluates the expression sum(sample) / len(sample) and then returns the result of the evaluation, which in this case is the value 2.5 .

A Python function will always have a return value. There is no notion of procedure or routine in Python. So, if you don’t explicitly use a return value in a return statement, or if you totally omit the return statement, then Python will implicitly return a default value for you. That default return value will always be None .

Say you’re writing a function that adds 1 to a number x , but you forget to supply a return statement. In this case, you’ll get an implicit return statement that uses None as a return value:

If you don’t supply an explicit return statement with an explicit return value, then Python will supply an implicit return statement using None as a return value. In the above example, add_one() adds 1 to x and stores the value in result but it doesn’t return result . That’s why you get value = None instead of value = 6 . To fix the problem, you need to either return result or directly return x + 1 .

An example of a function that returns None is print() . The goal of this function is to print objects to a text stream file, which is normally the standard output (your screen). So, this function doesn’t need an explicit return statement because it doesn’t return anything useful or meaningful:

The call to print() prints Hello, World to the screen. Since this is the purpose of print() , the function doesn’t need to return anything useful, so you get None as a return value.

Note: The Python interpreter doesn’t display None . So, to show a return value of None in an interactive session , you need to explicitly use print() .

Regardless of how long and complex your functions are, any function without an explicit return statement, or one with a return statement without a return value, will return None .

If you’re working in an interactive session, then you might think that printing a value and returning a value are equivalent operations. Consider the following two functions and their output:

Both functions seem to do the same thing. In both cases, you see Hello, World printed on your screen. There’s only a subtle visible difference—the single quotation marks in the second example. But take a look at what happens if you return another data type, say an int object:

There’s no visible difference now. In both cases, you can see 42 on your screen. That behavior can be confusing if you’re just starting with Python. You might think that returning and printing a value are equivalent actions.

Now, suppose you’re getting deeper into Python and you’re starting to write your first script. You open a text editor and type the following code:

add() takes two numbers, adds them, and returns the result. On line 5 , you call add() to sum 2 plus 2 . Since you’re still learning the difference between returning and printing a value, you might expect your script to print 4 to the screen. However, that’s not what happens, and you get nothing on your screen.

Try it out by yourself. Save your script to a file called adding.py and run it from your command line as follows:

If you run adding.py from your command line, then you won’t see any result on your screen. That’s because when you run a script, the return values of the functions that you call in the script don’t get printed to the screen like they do in an interactive session.

If you want that your script to show the result of calling add() on your screen, then you need to explicitly call print() . Check out the following update of adding.py :

Now, when you run adding.py , you’ll see the number 4 on your screen.

So, if you’re working in an interactive session, then Python will show the result of any function call directly to your screen. But if you’re writing a script and you want to see a function’s return value, then you need to explicitly use print() .

You can use a return statement to return multiple values from a function. To do that, you just need to supply several return values separated by commas.

For example, suppose you need to write a function that takes a sample of numeric data and returns a summary of statistical measures. To code that function, you can use the Python standard module statistics , which provides several functions for calculating mathematical statistics of numeric data.

Here’s a possible implementation of your function:

In describe() , you take advantage of Python’s ability to return multiple values in a single return statement by returning the mean, median, and mode of the sample at the same time. Note that, to return multiple values, you just need to write them in a comma-separated list in the order you want them returned.

Note: If your functions needs several different return types, then you’re dealing with a more complex scenario. In this case, you can get some help from How to Use Type Hints for Multiple Return Types in Python .

Once you’ve coded describe() , you can take advantage of a powerful Python feature known as iterable unpacking to unpack the three measures into three separated variables , or you can just store everything in one variable:

Here, you unpack the three return values of describe() into the variables mean , median , and mode . Note that in the last example, you store all the values in a single variable, desc , which turns out to be a Python tuple .

Note: You can build a Python tuple by just assigning several comma-separated values to a single variable. There’s no need to use parentheses to create a tuple . That’s why multiple return values are packed in a tuple .

The built-in function divmod() is also an example of a function that returns multiple values. The function takes two (non-complex) numbers as arguments and returns two numbers, the quotient of the two input values and the remainder of the division:

The call to divmod() returns a tuple containing the quotient and remainder that result from dividing the two non-complex numbers provided as arguments. This is an example of a function with multiple return values.

Using the Python return Statement: Best Practices

So far, you’ve covered the basics of how the Python return statement works. You now know how to write functions that return one or multiple values to the caller. Additionally, you’ve learned that if you don’t add an explicit return statement with an explicit return value to a given function, then Python will add it for you. That value will be None .

In this section, you’ll cover several examples that will guide you through a set of good programming practices for effectively using the return statement. These practices will help you to write more readable, maintainable, robust, and efficient functions in Python.

Some programmers rely on the implicit return statement that Python adds to any function without an explicit one. This can be confusing for developers who come from other programming languages in which a function without a return value is called a procedure .

There are situations in which you can add an explicit return None to your functions. In other situations, however, you can rely on Python’s default behavior:

If your function performs actions but doesn’t have a clear and useful return value, then you can omit returning None because doing that would just be superfluous and confusing. You can also use a bare return without a return value just to make clear your intention of returning from the function.

If your function has multiple return statements and returning None is a valid option, then you should consider the explicit use of return None instead of relying on the Python’s default behavior.

These practices can improve the readability and maintainability of your code by explicitly communicating your intent.

When it comes to returning None , you can use one of three possible approaches:

  • Omit the return statement and rely on the default behavior of returning None .
  • Use a bare return without a return value, which also returns None .
  • Return None explicitly.

Here’s how this works in practice:

Whether or not to return None explicitly is a personal decision. However, you should consider that in some cases, an explicit return None can avoid maintainability problems. This is especially true for developers who come from other programming languages that don’t behave like Python does.

When writing custom functions, you might accidentally forget to return a value from a function. In this case, Python will return None for you. This can cause subtle bugs that can be difficult for a beginning Python developer to understand and debug .

You can avoid this problem by writing the return statement immediately after the header of the function. Then you can make a second pass to write the function’s body. Here’s a template that you can use when coding your Python functions:

If you get used to starting your functions like this, then chances are that you’ll no longer miss the return statement. With this approach, you can write the body of the function, test it, and rename the variables once you know that the function works.

This practice can increase your productivity and make your functions less error-prone. It can also save you a lot of debugging time.

As you saw before, it’s a common practice to use the result of an expression as a return value in Python functions. If the expression that you’re using gets too complex, then this practice can lead to functions that are difficult to understand, debug, and maintain.

For example, if you’re doing a complex calculation, then it would be more readable to incrementally calculate the final result using temporary variables with meaningful names.

Consider the following function that calculates the variance of a sample of numeric data:

The expression that you use here is quite complex and difficult to understand. It’s also difficult to debug because you’re performing multiple operations in a single expression. To work around this particular problem, you can take advantage of an incremental development approach that improves the readability of the function.

Take a look at the following alternative implementation of variance() :

In this second implementation of variance() , you calculate the variance in several steps. Each step is represented by a temporary variable with a meaningful name.

Temporary variables like n , mean , and total_square_dev are often helpful when it comes to debugging your code. If, for example, something goes wrong with one of them, then you can call print() to know what’s happening before the return statement runs.

In general, you should avoid using complex expressions in your return statement. Instead, you can break your code into multiple steps and use temporary variables for each step. Using temporary variables can make your code easier to debug, understand, and maintain.

Functions that don’t have an explicit return statement with a meaningful return value often preform actions that have side effects . A side effect can be, for example, printing something to the screen, modifying a global variable , updating the state of an object, writing some text to a file , and so on.

Modifying global variables is generally considered a bad programming practice. Just like programs with complex expressions, programs that modify global variables can be difficult to debug, understand, and maintain.

When you modify a global variable, you’re potentially affecting all the functions, classes, objects, and any other parts of your programs that rely on that global variable.

To understand a program that modifies global variables, you need to be aware of all the parts of the program that can see, access, and change those variables. So, good practice recommends writing self-contained functions that take some arguments and return a useful value (or values) without causing any side effect on global variables.

Additionally, functions with an explicit return statement that return a meaningful value are easier to test than functions that modify or update global variables.

The following example show a function that changes a global variable. The function uses the global statement , which is also considered a bad programming practice in Python:

In this example, you first create a global variable, counter , with an initial value of 0 . Inside increment() , you use a global statement to tell the function that you want to modify a global variable. The last statement increments counter by 1 .

The result of calling increment() will depend on the initial value of counter . Different initial values for counter will generate different results, so the function’s result can’t be controlled by the function itself.

To avoid this kind of behavior, you can write a self-contained increment() that takes arguments and returns a coherent value that depends only on the input arguments:

Now the result of calling increment() depends only on the input arguments rather than on the initial value of counter . This makes the function more robust and easier to test.

Note: For a better understanding of how to test your Python code, check out Test-Driven Development With PyTest .

If you’d like a deeper dive into using global variables in functions, then Using and Creating Global Variables in Your Python Functions is for you.

Additionally, when you need to update counter , you can do so explicitly with a call to increment() . This way, you’ll have more control over what’s happening with counter throughout your code.

In general, it’s a good practice to avoid functions that modify global variables. If possible, try to write self-contained functions with an explicit return statement that returns a coherent and meaningful value.

Python functions are not restricted to having a single return statement. If a given function has more than one return statement, then the first one encountered will determine the end of the function’s execution and also its return value.

A common way of writing functions with multiple return statements is to use conditional statements that allow you to provide different return statements depending on the result of evaluating some conditions.

Suppose you need to code a function that takes a number and returns its absolute value . If the number is greater than 0 , then you’ll return the same number. If the number is less than 0 , then you’ll return its opposite, or non-negative value.

Here’s a possible implementation for this function:

my_abs() has two explicit return statements, each of them wrapped in its own if statement . It also has an implicit return statement. If number happens to be 0 , then neither condition is true, and the function ends without hitting any explicit return statement. When this happens, you automatically get None .

Take a look at the following call to my_abs() using 0 as an argument:

When you call my_abs() using 0 as an argument, you get None as a result. That’s because the flow of execution gets to the end of the function without reaching any explicit return statement. Unfortunately, the absolute value of 0 is 0 , not None .

To fix this problem, you can add a third return statement, either in a new elif clause or in a final else clause:

Now, my_abs() checks every possible condition, number > 0 , number < 0 , and number == 0 . The purpose of this example is to show that when you’re using conditional statements to provide multiple return statements, you need to make sure that every possible option gets its own return statement. Otherwise, your function will have a hidden bug.

Finally, you can implement my_abs() in a more concise, efficient, and Pythonic way using a single if statement:

In this case, your function hits the first return statement if number < 0 . In all other cases, whether number > 0 or number == 0 , it hits the second return statement. With this new implementation, your function looks a lot better. It’s more readable, concise, and efficient.

Note: There’s a convenient built-in Python function called abs() for computing the absolute value of a number. The function in the above example is intended only to illustrate the point under discussion.

If you’re using if statements to provide several return statements, then you don’t need an else clause to cover the last condition. Just add a return statement at the end of the function’s code block and at the first level of indentation.

Another common use case for the combination of if and return statements is when you’re coding a predicate or Boolean-valued function. This kind of function returns either True or False according to a given condition.

For example, say you need to write a function that takes two integers, a and b , and returns True if a is divisible by b . Otherwise, the function should return False . Here’s a possible implementation:

is_divisible() returns True if the remainder of dividing a by b is equal to 0 . Otherwise, it returns False . Note that in Python, a 0 value is falsy , so you need to use the not operator to negate the truth value of the condition.

Sometimes you’ll write predicate functions that involve operators like the following:

  • The comparison operators == , != , > , >= , < , and <=
  • The membership operator in
  • The identity operator is
  • The Boolean operator not

In these cases, you can directly use a Boolean expression in your return statement. This is possible because these operators return either True or False . Following this idea, here’s a new implementation of is_divisible() :

If a is divisible by b , then a % b returns 0 , which is falsy in Python. So, to return True , you need to use the not operator.

Note: Python follows a set of rules to determine the truth value of an object.

For example, the following objects are considered falsy :

  • Constants like None and False
  • Numeric types with a zero value like 0 , 0.0 , 0j , Decimal(0) , and Fraction(0, 1)
  • Empty sequences and collections like "" , () , [] , {} , set() , and range(0)
  • Objects that implement __bool__() with a return value of False or __len__() with a return value of 0

Any other object will be considered truthy.

On the other hand, if you try to use conditions that involve Boolean operators like or and and in the way you saw before, then your predicate functions won’t work correctly. That’s because these operators behave differently. They return one of the operands in the condition rather than True or False :

In general, and returns the first false operand or the last operand. On the other hand, or returns the first true operand or the last operand. So, to write a predicate that involves one of these operators, you’ll need to use an explicit if statement or a call to the built-in function bool() .

Suppose you want to write a predicate function that takes two values and returns True if both are true and False otherwise. Here’s your first approach to this function:

Since and returns operands instead of True or False , your function doesn’t work correctly. There are at least three possibilities for fixing this problem:

  • An explicit if statement
  • A conditional expression (ternary operator)
  • The built-in Python function bool()

If you use the first approach, then you can write both_true() as follows:

The if statement checks if a and b are both truthy. If so, then both_true() returns True . Otherwise, it returns False .

If, on the other hand, you use a Python conditional expression or ternary operator, then you can write your predicate function as follows:

Here, you use a conditional expression to provide a return value for both_true() . The conditional expression is evaluated to True if both a and b are truthy. Otherwise, the final result is False .

Finally, if you use bool() , then you can code both_true() as follows:

bool() returns True if a and b are true and False otherwise. It’s up to you what approach to use for solving this problem. However, the second solution seems more readable. What do you think?

A return statement inside a loop performs some kind of short-circuit . It breaks the loop execution and makes the function return immediately. To better understand this behavior, you can write a function that emulates any() . This built-in function takes an iterable and returns True if at least one of its items is truthy.

To emulate any() , you can code a function like the following:

If any item in iterable is true, then the flow of execution enters in the if block. The return statement breaks the loop and returns immediately with a return value of True . If no value in iterable is true, then my_any() returns False .

This function implements a short-circuit evaluation . For example, suppose that you pass an iterable that contains a million items. If the first item in that iterable happens to be true, then the loop runs only one time rather than a million times. This can save you a lot of processing time when running your code.

It’s important to note that to use a return statement inside a loop, you need to wrap the statement in an if statement. Otherwise, the loop will always break in its first iteration.

As soon as a function hits a return statement, it terminates without executing any subsequent code. Consequently, the code that appears after the function’s return statement is commonly called dead code . The Python interpreter totally ignores dead code when running your functions. So, having that kind of code in a function is useless and confusing.

Consider the following function, which adds code after its return statement:

The statement print("Hello, World") in this example will never execute because that statement appears after the function’s return statement. Identifying dead code and removing it is a good practice that you can apply to write better functions.

It’s worth noting that if you’re using conditional statements to provide multiple return statements, then you can have code after a return statement that won’t be dead as long as it’s outside the if statement:

Even though the call to print() is after a return statement, it’s not dead code. When condition is evaluated to False , the print() call is run and you get Hello, World printed to your screen.

When you’re writing a function that returns multiple values in a single return statement, you can consider using a collections.namedtuple object to make your functions more readable. namedtuple is a collection class that returns a subclass of tuple that has fields or attributes. You can access those attributes using dot notation or an indexing operation .

The initializer of namedtuple takes several arguments. However, to start using namedtuple in your code, you just need to know about the first two:

  • typename holds the name of the tuple-like class that you’re creating. It needs to be a string.
  • field_names holds the names of the fields or attributes of the tuple-like class. It can be a sequence of strings such as ["x", "y"] or a single string with each name separated by whitespace or commas, such as "x y" or "x, y" .

Using a namedtuple when you need to return multiple values can make your functions significantly more readable without too much effort. Consider the following update of describe() using a namedtuple as a return value:

Inside describe() , you create a namedtuple called Desc . This object can have named attributes that you can access by using dot notation or by using an indexing operation. In this example, those attributes are "mean" , "median" , and "mode" .

You can create a Desc object and use it as a return value. To do that, you need to instantiate Desc like you’d do with any Python class. Note that you need to supply a concrete value for each named attribute, just like you did in your return statement.

Here’s how describe() works now:

When you call describe() with a sample of numeric data, you get a namedtuple object containing the mean, median, and mode of the sample. Note that you can access each element of the tuple by using either dot notation or an indexing operation.

Finally, you can also use an iterable unpacking operation to store each value in its own independent variable.

In Python, functions are first-class objects . A first-class object is an object that can be assigned to a variable, passed as an argument to a function, or used as a return value in a function. So, you can use a function object as a return value in any return statement.

A function that takes a function as an argument, returns a function as a result, or both is a higher-order function . A closure factory function is a common example of a higher-order function in Python. This kind of function takes some arguments and returns an inner function . The inner function is commonly known as a closure .

A closure carries information about its enclosing execution scope. This provides a way to retain state information between function calls. Closure factory functions are useful when you need to write code based on the concept of lazy or delayed evaluation .

Suppose you need to write a helper function that takes a number and returns the result of multiplying that number by a given factor. You can code that function as follows:

by_factor() takes factor and number as arguments and returns their product. Since factor rarely changes in your application, you find it annoying to supply the same factor in every function call. So, you need a way to retain the state or value of factor between calls to by_factor() and change it only when needed. To retain the current value of factor between calls, you can use a closure.

The following implementation of by_factor() uses a closure to retain the value of factor between calls:

Inside by_factor() , you define an inner function called multiply() and return it without calling it. The function object you return is a closure that retains information about the state of factor . In other words, it remembers the value of factor between calls. That’s why double remembers that factor was equal to 2 and triple remembers that factor was equal to 3 .

Note that you can freely reuse double and triple because they don’t forget their respective state information.

You can also use a lambda function to create closures. Sometimes the use of a lambda function can make your closure factory more concise. Here’s an alternative implementation of by_factor() using a lambda function:

This implementation works just like the original example. In this case, the use of a lambda function provides a quick and concise way to code by_factor() .

Another way of using the return statement for returning function objects is to write decorator functions . A decorator function takes a function object as an argument and returns a function object. The decorator processes the decorated function in some way and returns it or replaces it with another function or callable object.

Decorators are useful when you need to add extra logic to existing functions without modifying them. For example, you can code a decorator to log function calls, validate the arguments to a function, measure the execution time of a given function, and so on.

The following example shows a decorator function that you can use to get an idea of the execution time of a given Python function:

The syntax @my_timer above the header of delayed_mean() is equivalent to the expression delayed_mean = my_timer(delayed_mean) . In this case, you can say that my_timer() is decorating delayed_mean() .

Python runs decorator functions as soon as you import or run a module or a script. So, when you call delayed_mean() , you’re really calling the return value of my_timer() , which is the function object _timer . The call to the decorated delayed_mean() will return the mean of the sample and will also measure the execution time of the original delayed_mean() .

In this case, you use time() to measure the execution time inside the decorator. time() lives in a module called time that provides a set of time-related functions. time() returns the time in seconds since the epoch as a floating-point number. The difference between the time before and after the call to delayed_mean() will give you an idea of the function’s execution time.

Note: In delayed_mean() , you use the function time.sleep() , which suspends the execution of the calling code for a given number of seconds. For a better understanding on how to use sleep() , check out Python sleep(): How to Add Time Delays to Your Code .

Other common examples of decorators in Python are classmethod() , staticmethod() , and property() . If you want to dive deeper into Python decorators, then take a look at Primer on Python Decorators . You can also check out Python Decorators 101 .

The Python return statement can also return user-defined objects . In other words, you can use your own custom objects as a return value in a function. A common use case for this capability is the factory pattern .

The factory pattern defines an interface for creating objects on the fly in response to conditions that you can’t predict when you’re writing a program. You can implement a factory of user-defined objects using a function that takes some initialization arguments and returns different objects according to the concrete input.

Say you’re writing a painting application. You need to create different shapes on the fly in response to your user’s choices. Your program will have squares, circles, rectangles, and so on. To create those shapes on the fly, you first need to create the shape classes that you’re going to use:

Once you have a class for each shape, you can write a function that takes the name of the shape as a string and an optional list of arguments ( *args ) and keyword arguments ( **kwargs ) to create and initialize shapes on the fly:

This function creates an instance of the concrete shape and returns it to the caller. Now you can use shape_factory() to create objects of different shapes in response to the needs of your users:

If you call shape_factory() with the name of the required shape as a string, then you get a new instance of the shape that matches the shape_name you’ve just passed to the factory.

When you use a return statement inside a try statement with a finally clause, that finally clause is always executed before the return statement. This ensures that the code in the finally clause will always run. Check out the following example:

When you call func() , you get value converted to a floating-point number or a string object. Before doing that, your function runs the finally clause and prints a message to your screen. Whatever code you add to the finally clause will be executed before the function runs its return statement.

A Python function with a yield statement in its body is a generator function . When you call a generator function, it returns a generator iterator . So, you can say that a generator function is a generator factory .

You can use a return statement inside a generator function to indicate that the generator is done. The return statement will make the generator raise a StopIteration . The return value will be passed as an argument to the initializer of StopIteration and will be assigned to its .value attribute.

Here’s a generator that yields 1 and 2 on demand and then returns 3 :

gen() returns a generator object that yields 1 and 2 on demand. To retrieve each number form the generator object, you can use next() , which is a built-in function that retrieves the next item from a Python generator.

The first two calls to next() retrieve 1 and 2 , respectively. In the third call, the generator is exhausted, and you get a StopIteration . Note that the return value of the generator function ( 3 ) becomes the .value attribute of the StopIteration object.

The Python return statement allows you to send any Python object from your custom functions back to the caller code. This statement is a fundamental part of any Python function or method. If you master how to use it, then you’ll be ready to code robust functions.

Next, you’ll find common questions that sum up the most important concepts you’ve learned in this tutorial. You can use these questions to check, recap, and solidify your knowledge. After each question, you’ll find an answer hidden in a collapsible section. Click the Show/Hide toggle to reveal it. But first, try to come up with the answer on your own.

What’s the difference between explicit and implicit return statements? Show/Hide

An explicit return statement immediately ends the function’s execution and sends the specified value back to the caller. For example, a function can return a number, a list, or any other object. If no return statement is present, Python adds one implicitly, which returns None .

How do I return single or multiple values from my functions to the caller code? Show/Hide

In Python, the return statement allows you to send values back to the caller from a function. To return a single value, use the return keyword followed by the value. This can be any data type, such as a number, string, list, or object.

To return multiple values, list them after the return keyword separated by commas. Python packs these values into a tuple. You can then unpack the tuple into separate variables or store it as a single variable.

What are the best practices I should apply when using the return statement? Show/Hide

First, explicitly return None when appropriate. If your function should return None , do so explicitly with return None for clarity. However, if your function performs actions without a clear return value, you can omit the return statement and rely on Python implicitly returning None .

Additionally, avoid complex return expressions. Instead, break them down to improve readability and debugging. You can also use short-circuiting in loops to simplify your code. Employ return statements inside loops to exit early when a condition is met, saving processing time.

You should also prefer self-contained functions over those that modify global variables, and when using conditional returns, handle all possible conditions with appropriate return statements to avoid hidden bugs.

How do I code a closure factory function? Show/Hide

Creating a closure factory function involves making a function that returns another function. This inner function retains access to the variables from the outer function. It’s perfect for situations where you want to keep some state information between calls.

How do I code a decorator function? Show/Hide

For decorator functions , you write a function that takes another function, adds some extra functionality, and returns this new function. Decorators are great for tasks like logging and timing that aren’t central to the original function’s purpose.

Do you want to take a quick quiz to evaluate your new skills? If so, then click the link below:

🐍 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 Leodanis Pozo Ramos

Leodanis Pozo Ramos

Leodanis is an industrial engineer who loves Python and software development. He's a self-taught Python developer with 6+ years of experience. He's an avid technical writer with a growing number of articles published on Real Python and other sites.

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 best-practices python

Recommended Video Course: Using the Python return Statement Effectively

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

Already have an account? Sign-In

Almost there! Complete this form and click the button below to gain instant access:

Python Logo

5 Thoughts On Python Mastery

🔒 No spam. We take your privacy seriously.

assignment statement return

  • 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.

confused with return value of assignment operation in java

I tried to understand how exactly the return value of assignment operation works. followed by this post "Java returns the assigned value".

b2 is true because of (b1 == false) return true, then the return of b2 assignment b2 = true

Or is it because of some other reason?

Graham's user avatar

  • its the game of precedence of assignment and equal to . @Pau –  jack jay Commented Jan 7, 2017 at 16:34
  • See here: docs.oracle.com/javase/tutorial/java/nutsandbolts/… –  GhostCat Commented Jan 7, 2017 at 16:42

You've got it right. The operator precedence rules make sure that first the == operator is evaluated. That's b1==false , yielding true. After that, the assigned is executed, setting b2 to true. Finally, the assignment operator returns the value as b2, which is evaluated by the if statement.

Stephan Rauh's user avatar

  • int i = doIt() / (j = 2); , why the method execution comes before the grouping & accessing operators ? they are in the top level of Operator Precedence and Parentheses .thanks –  Pauwelyn Commented Jan 11, 2017 at 19:09
  • Java usually evaluates the terms from the left to the right (pretty much like we humans do, at least in the western hemisphere). So we start with doIt . Next thing we see is a () . That's top priority, so we call the function. After that we encounter the / , priority 13. It's followed by another ( , priority 16. So we evaluate j=2 first. Having done that, we return to the division. That happens to be the last step in the evaluation. –  Stephan Rauh Commented Jan 12, 2017 at 22:16
  • Another possible explanation is that doIt() is a singular term. In Java, you can't do anything with the name of a method. Other programming languages may treat it as an useful entity of its own (function pointers, lambda expression etc.). Java doesn't do such a thing. If it finds a method name in an expression, the only sensible thing to do is to execute it. From this point of view, doIt and () belong together and can't be separated. They are a single, atomar term of the expression. Little wonder the method is evaluated first, no matter what comes next. –  Stephan Rauh Commented Jan 12, 2017 at 22:21

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 java or ask your own question .

  • The Overflow Blog
  • Unpacking the 2024 Developer Survey results
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Introducing an accessibility dashboard and some upcoming changes to display...
  • Tag hover experiment wrap-up and next steps

Hot Network Questions

  • Solving the "reverse" Assignment Problem?
  • What are these red pointy flower buds with heart-shaped leaves?
  • Wall of Fire: Taking damage multiple times by using forced movement on a target
  • What type of concept is "mad scientist"?
  • Mathematical Theory of Monotone Transforms
  • What happened to MOSBD?
  • "Continuity" in a metric space
  • Who‘s to say that beliefs held because of rational reasons are indeed more justified than beliefs held because of emotional ones
  • Refereeing papers by people you are very close to
  • Is there a pre-defined compiler macro for legacy Microsoft C 5.10 to get the compiler's name and version number?
  • Why is the completely dark disk of the Moon visible on a new moon if the lunar orbit is at an angle to the Earth’s?
  • Iterative mixing problem
  • Short story about a mean man invaded by an extraterrestrial being who later became calm and kind and his wife denying alien presence to the police
  • Can the Bible be the word of God, when there are multiple versions of it?
  • English equivalent to the famous Hindi proverb "the marriage sweetmeat: those who eat it regret, and those who don't eat it also regret"?
  • Arduino Board Getting Too Hot: Need Help Diagnosing Issue (Schematic Provided)
  • Why are my IK rigged legs shaking/jiterring?
  • Are story points really a good measure for velocity?
  • Netgate 6100 Will Not Acknowledge Lastest Versions of pfSense (When Checking For Updates)
  • Design patterns - benefits of using with Apex code
  • unable to mount external hard disk in 24.04
  • If it's true that a reservation fee for a cruise ship is non-refundable, then what happens if somebody cancels?
  • If a planet or star is composed of gas, the center of mass will have zero gravity but immense pressure? I'm trying to understand fusion in stars
  • How bright would nights be if the moon were terraformed?

assignment statement return

IMAGES

  1. 1.4. Expressions and Assignment Statements

    assignment statement return

  2. What are Assignment Statement: Definition, Assignment Statement Forms

    assignment statement return

  3. PPT

    assignment statement return

  4. PPT

    assignment statement return

  5. Assignment Statement

    assignment statement return

  6. PPT

    assignment statement return

COMMENTS

  1. c

    The rule is to return the right-hand operand of = converted to the type of the variable which is assigned to. int a; float b; a = b = 4.5; // 4.5 is a double, it gets converted to float and stored into b. // this returns a float which is converted to an int and stored in a. // the whole expression returns an int.

  2. 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 generator function, the return statement indicates that the generator is done and will ...

  3. Python's Assignment Operator: Write Robust Assignments

    To create a new variable or to update the value of an existing one in Python, you'll use an assignment statement. This statement has the following three components: A left operand, which must be a variable. The assignment operator ( =) A right operand, which can be a concrete value, an object, or an expression.

  4. Assignment (computer science)

    Assignment (computer science) In computer programming, an assignment statement sets and/or re-sets the value stored in the storage location (s) denoted by a variable name; in other words, it copies a value into the variable. In most imperative programming languages, the assignment statement (or expression) is a fundamental construct.

  5. What is the benefit of having the assignment operator return a value?

    Python makes assignment a proper statement instead of an expression. Proposals for changing this occasionally reach the python-ideas mailing list, but my subjective impression is that this happens more rarely and generates less noise each time compared to other "missing" features like do-while loops, switch statements, multi-line lambdas, etc.

  6. Assignment operators

    for assignments to class type objects, the right operand could be an initializer list only when the assignment is defined by a user-defined assignment operator. removed user-defined assignment constraint. CWG 1538. C++11. E1 ={E2} was equivalent to E1 = T(E2) ( T is the type of E1 ), this introduced a C-style cast. it is equivalent to E1 = T{E2}

  7. Assignment operators

    the assignment statement. B = A; can have one of the following effects: ... The built-in assignment operators return the value of the object specified by the left operand after the assignment (and the arithmetic/logical operation in the case of compound assignment operators). The resultant type is the type of the left operand.

  8. Assignment Statement in Python

    Learn the basics of assignment statements in Python in this tutorial. We'll cover the syntax and usage of the assignment operator, including multiple assignm...

  9. PEP 572

    Unparenthesized assignment expressions are prohibited as annotations for arguments, return values and assignments. Example: ... 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 ...

  10. Different Forms of Assignment Statements in Python

    Multiple- target assignment: x = y = 75. print(x, y) In this form, Python assigns a reference to the same object (the object which is rightmost) to all the target on the left. OUTPUT. 75 75. 7. Augmented assignment : The augmented assignment is a shorthand assignment that combines an expression and an assignment.

  11. Assignment Operators in Programming

    Assignment operators are used in programming to assign values to variables. We use an assignment operator to store and update data within a program. ... Conditional Statements: Assigning different values based on conditions in conditional statements. Function Return Values: Storing the return values of functions in variables. Data Manipulation: ...

  12. 1.7 Java

    An assignment statement designates a value for a variable. An assignment statement can be used as an expression in Java. After a variable is declared, you can assign a value to it by using an assignment statement. In Java, the equal sign = is used as the assignment operator. The syntax for assignment statements is as follows: variable ...

  13. c++

    The expression Traficlight::yellow would be an rvalue, and your function returns a reference to t after changing t 's value, which is an lvalue. Assignment operator= on its own returns a reference to its left argument. The code is ill-formed, some old compilers consider it IFNDR. One thing though post-increment operator++ in expression Trafic++ ...

  14. What are Assignment Statement: Definition, Assignment Statement ...

    Assignment Statement. An Assignment statement is a statement that is used to set a value to the variable name in a program. Assignment statement allows a variable to hold different types of values during its program lifespan. Another way of understanding an assignment statement is, it stores a value in the memory location which is denoted.

  15. Assignment Operators in C

    1. "=": This is the simplest assignment operator. This operator is used to assign the value on the right to the variable on the left. Example: a = 10; b = 20; ch = 'y'; 2. "+=": This operator is combination of '+' and '=' operators. This operator first adds the current value of the variable on left to the value on the right and ...

  16. Assignment (=)

    The assignment operator is completely different from the equals (=) sign used as syntactic separators in other locations, which include:Initializers of var, let, and const declarations; Default values of destructuring; Default parameters; Initializers of class fields; All these places accept an assignment expression on the right-hand side of the =, so if you have multiple equals signs chained ...

  17. javascript

    That's the way the language was designed. It is consistent with most languages. Having a variable declaration return anything other than undefined is meaningless, because you can't ever use the var keyword in an expression context.. Having assignment be an expression not a statement is useful when you want to set many variable to the same value at once:. x = y = z = 2;

  18. The Python return Statement: Usage and Best Practices

    Understanding the Python return Statement. The Python return statement is a special statement that you can use inside a function or method to send the function's result back to the caller. A return statement consists of the return keyword followed by an optional return value.. The return value of a Python function can be any Python object. Everything in Python is an object.

  19. python

    7. In a return statement, only an expression can come after the "return". return_stmt ::= "return" [expression_list] An assignment is a statement. You can't put a statement after "return", because a statement isn't an expression. Consider skipping the assignment entirely. Just return will suffice: return 100.

  20. A look at Walz's progressive policies as Minnesota's governor

    The Assignment with Audie Cornish ... though they do need to file a tax return to claim the credit. ... Walz said in a statement last week. The average credit was $1,244 per child - totaling ...

  21. confused with return value of assignment operation in java

    4. You've got it right. The operator precedence rules make sure that first the == operator is evaluated. That's b1==false, yielding true. After that, the assigned is executed, setting b2 to true. Finally, the assignment operator returns the value as b2, which is evaluated by the if statement. answered Jan 7, 2017 at 16:35.