avatar

Python Course #12: Pass by Assignment, Copy, Reference, and None

Now that the you know what mutable (e.g. lists , sets and dictionaries ) and immutable data types (e.g. tuples ) are it is important to talk about copies, references and None .

Python Pass by Assignment

When you call a pass data to a function such as print(...) there are two ways. The first option is to pass the data directly as a value:

The second option is to pass the data as a variable:

The difference between those two options is that the second option allows you to access the data you passed to the function later in your program by stating the variable. When the function that receives the data modifies it internally, you have to be aware of two critical things:

When a primitive data type ( bool , int , float , and str ) or immutable data type (e.g. tuple ) is passed to a function, its value is copied. Therefore, all changes made inside a function won’t affect the values stored in the variables passed to the function. This is called pass by value .

When a mutable data type (e.g. list , set , dict ) is passed to a function, the data isn’t copied. Because of this, changes that are made inside the function affect the values outside of the function. This is called pass by reference

This sounds pretty theoretical, so here comes an example:

Even though you haven’t learned about declaring functions in Python this example declares the function func(x, y) that takes two parameters. func(x, y) subtracts 1 from the first parameter, and calls pop() on the second one. That is everything you need to understand at the moment.

In the main program, the int i and the list l are declared and then passed to func(x, y) . When looking at i and l after func(x, y) has been executed, you can see that i is still 1 and not 0 because i ’s value was copied. However, l is missing its last element since it was passed as a reference.

This mix of pass by value and pass by reference in Python is called pass by assignment . It is essential to keep this concept always in mind when writing Python code.

In the previous parts of this Python course, you have seen that it is possible to get a copy of a mutable data type by calling the .copy() function:

By using .copy() , the data outside of the function isn’t changed.

In the following example the difference between a copy and reference is further amplified:

In the first line the list ['a', 'b', 'c'] is declared and than a new reference to this list is created with l = . In the second line another reference to the list ['a', 'b', 'c'] is created with: m = l . In the third line the list is copied and a reference to that copy is created with: n = l.copy() .

There are three references to two lists with the same content. l and m reference the first list and n reference the second list . Because l and m reference the same list every modification done using l or m will always be reflected in both. n won’t change as it references a different list .

Python is vs ==

To check if two variables reference the same value you can use the is operator to compare the values use the == operator:

l is n evaluates to False because they reference differnt list s, however, those two list s contain the same values and therefore l == n evaluates to True . You can also check the id that a variable is referencing using id(...) :

You can see that the id of l and m is the same and the id of n is different (The numbers are different everytime you run this code). The is operator is actually implemented using == with id(...) == id(...) .

Python None

Now that you know the difference between a copy and a reference, there is one last thing to talk about: ` None . The keyword None in Python indicates no value at all. And there is only one None`:

None can be used to initialize a variable without assigning a value. This can be useful when the value of a variable is assigned under a condition:

None actually has it’s own type and is an immutable data type because it can’t be changed:

None concludes this article. Throughout this Python course, you will come across pass by assignment, copies, references, and None reasonably often. Make sure to get the free Python Cheat Sheets in my Gumroad shop . If you have any questions about this article, feel free to join our Discord community to ask them over there.

Further Reading

Big o notation explained.

Why is Big O Notation Used? When you got different algorithms to solve the same problem, you need to compare those to each other to pick the best (meaning fastest) for your program. Looking at eac...

Python Course #2: Variables and Primitive Datatypes for Absolute Beginners

After you have written your first Python Hello World program (find the article over here: Python Lesson 1: Your First Python Program (Complete Beginners Guide) ) it is time to talk about variables ...

Python Course #3: Introduction to Boolean Algebra

The term Boolean algebra itself might sound dry and dull, but it is one of the backbones of all the computers we use today. In this article, you will learn what Boolean algebra is and how to use it...

Estimate Gas in Ethereum Transactions with Python web3 and brownie

Change Windows 10/11 Display Resolution with a Python System Tray Application

Trending Tags

  • Python »
  • 3.12.3 Documentation »
  • The Python Standard Library »
  • Text Processing Services »
  • string — Common string operations
  • Theme Auto Light Dark |

string — Common string operations ¶

Source code: Lib/string.py

Text Sequence Type — str

String Methods

String constants ¶

The constants defined in this module are:

The concatenation of the ascii_lowercase and ascii_uppercase constants described below. This value is not locale-dependent.

The lowercase letters 'abcdefghijklmnopqrstuvwxyz' . This value is not locale-dependent and will not change.

The uppercase letters 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . This value is not locale-dependent and will not change.

The string '0123456789' .

The string '0123456789abcdefABCDEF' .

The string '01234567' .

String of ASCII characters which are considered punctuation characters in the C locale: !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ .

String of ASCII characters which are considered printable. This is a combination of digits , ascii_letters , punctuation , and whitespace .

A string containing all ASCII characters that are considered whitespace. This includes the characters space, tab, linefeed, return, formfeed, and vertical tab.

Custom String Formatting ¶

The built-in string class provides the ability to do complex variable substitutions and value formatting via the format() method described in PEP 3101 . The Formatter class in the string module allows you to create and customize your own string formatting behaviors using the same implementation as the built-in format() method.

The Formatter class has the following public methods:

The primary API method. It takes a format string and an arbitrary set of positional and keyword arguments. It is just a wrapper that calls vformat() .

Changed in version 3.7: A format string argument is now positional-only .

This function does the actual work of formatting. It is exposed as a separate function for cases where you want to pass in a predefined dictionary of arguments, rather than unpacking and repacking the dictionary as individual arguments using the *args and **kwargs syntax. vformat() does the work of breaking up the format string into character data and replacement fields. It calls the various methods described below.

In addition, the Formatter defines a number of methods that are intended to be replaced by subclasses:

Loop over the format_string and return an iterable of tuples ( literal_text , field_name , format_spec , conversion ). This is used by vformat() to break the string into either literal text, or replacement fields.

The values in the tuple conceptually represent a span of literal text followed by a single replacement field. If there is no literal text (which can happen if two replacement fields occur consecutively), then literal_text will be a zero-length string. If there is no replacement field, then the values of field_name , format_spec and conversion will be None .

Given field_name as returned by parse() (see above), convert it to an object to be formatted. Returns a tuple (obj, used_key). The default version takes strings of the form defined in PEP 3101 , such as “0[name]” or “label.title”. args and kwargs are as passed in to vformat() . The return value used_key has the same meaning as the key parameter to get_value() .

Retrieve a given field value. The key argument will be either an integer or a string. If it is an integer, it represents the index of the positional argument in args ; if it is a string, then it represents a named argument in kwargs .

The args parameter is set to the list of positional arguments to vformat() , and the kwargs parameter is set to the dictionary of keyword arguments.

For compound field names, these functions are only called for the first component of the field name; subsequent components are handled through normal attribute and indexing operations.

So for example, the field expression ‘0.name’ would cause get_value() to be called with a key argument of 0. The name attribute will be looked up after get_value() returns by calling the built-in getattr() function.

If the index or keyword refers to an item that does not exist, then an IndexError or KeyError should be raised.

Implement checking for unused arguments if desired. The arguments to this function is the set of all argument keys that were actually referred to in the format string (integers for positional arguments, and strings for named arguments), and a reference to the args and kwargs that was passed to vformat. The set of unused args can be calculated from these parameters. check_unused_args() is assumed to raise an exception if the check fails.

format_field() simply calls the global format() built-in. The method is provided so that subclasses can override it.

Converts the value (returned by get_field() ) given a conversion type (as in the tuple returned by the parse() method). The default version understands ‘s’ (str), ‘r’ (repr) and ‘a’ (ascii) conversion types.

Format String Syntax ¶

The str.format() method and the Formatter class share the same syntax for format strings (although in the case of Formatter , subclasses can define their own format string syntax). The syntax is related to that of formatted string literals , but it is less sophisticated and, in particular, does not support arbitrary expressions.

Format strings contain “replacement fields” surrounded by curly braces {} . Anything that is not contained in braces is considered literal text, which is copied unchanged to the output. If you need to include a brace character in the literal text, it can be escaped by doubling: {{ and }} .

The grammar for a replacement field is as follows:

In less formal terms, the replacement field can start with a field_name that specifies the object whose value is to be formatted and inserted into the output instead of the replacement field. The field_name is optionally followed by a conversion field, which is preceded by an exclamation point '!' , and a format_spec , which is preceded by a colon ':' . These specify a non-default format for the replacement value.

See also the Format Specification Mini-Language section.

The field_name itself begins with an arg_name that is either a number or a keyword. If it’s a number, it refers to a positional argument, and if it’s a keyword, it refers to a named keyword argument. An arg_name is treated as a number if a call to str.isdecimal() on the string would return true. If the numerical arg_names in a format string are 0, 1, 2, … in sequence, they can all be omitted (not just some) and the numbers 0, 1, 2, … will be automatically inserted in that order. Because arg_name is not quote-delimited, it is not possible to specify arbitrary dictionary keys (e.g., the strings '10' or ':-]' ) within a format string. The arg_name can be followed by any number of index or attribute expressions. An expression of the form '.name' selects the named attribute using getattr() , while an expression of the form '[index]' does an index lookup using __getitem__() .

Changed in version 3.1: The positional argument specifiers can be omitted for str.format() , so '{} {}'.format(a, b) is equivalent to '{0} {1}'.format(a, b) .

Changed in version 3.4: The positional argument specifiers can be omitted for Formatter .

Some simple format string examples:

The conversion field causes a type coercion before formatting. Normally, the job of formatting a value is done by the __format__() method of the value itself. However, in some cases it is desirable to force a type to be formatted as a string, overriding its own definition of formatting. By converting the value to a string before calling __format__() , the normal formatting logic is bypassed.

Three conversion flags are currently supported: '!s' which calls str() on the value, '!r' which calls repr() and '!a' which calls ascii() .

Some examples:

The format_spec field contains a specification of how the value should be presented, including such details as field width, alignment, padding, decimal precision and so on. Each value type can define its own “formatting mini-language” or interpretation of the format_spec .

Most built-in types support a common formatting mini-language, which is described in the next section.

A format_spec field can also include nested replacement fields within it. These nested replacement fields may contain a field name, conversion flag and format specification, but deeper nesting is not allowed. The replacement fields within the format_spec are substituted before the format_spec string is interpreted. This allows the formatting of a value to be dynamically specified.

See the Format examples section for some examples.

Format Specification Mini-Language ¶

“Format specifications” are used within replacement fields contained within a format string to define how individual values are presented (see Format String Syntax and f-strings ). They can also be passed directly to the built-in format() function. Each formattable type may define how the format specification is to be interpreted.

Most built-in types implement the following options for format specifications, although some of the formatting options are only supported by the numeric types.

A general convention is that an empty format specification produces the same result as if you had called str() on the value. A non-empty format specification typically modifies the result.

The general form of a standard format specifier is:

If a valid align value is specified, it can be preceded by a fill character that can be any character and defaults to a space if omitted. It is not possible to use a literal curly brace (” { ” or “ } ”) as the fill character in a formatted string literal or when using the str.format() method. However, it is possible to insert a curly brace with a nested replacement field. This limitation doesn’t affect the format() function.

The meaning of the various alignment options is as follows:

Note that unless a minimum field width is defined, the field width will always be the same size as the data to fill it, so that the alignment option has no meaning in this case.

The sign option is only valid for number types, and can be one of the following:

The 'z' option coerces negative zero floating-point values to positive zero after rounding to the format precision. This option is only valid for floating-point presentation types.

Changed in version 3.11: Added the 'z' option (see also PEP 682 ).

The '#' option causes the “alternate form” to be used for the conversion. The alternate form is defined differently for different types. This option is only valid for integer, float and complex types. For integers, when binary, octal, or hexadecimal output is used, this option adds the respective prefix '0b' , '0o' , '0x' , or '0X' to the output value. For float and complex the alternate form causes the result of the conversion to always contain a decimal-point character, even if no digits follow it. Normally, a decimal-point character appears in the result of these conversions only if a digit follows it. In addition, for 'g' and 'G' conversions, trailing zeros are not removed from the result.

The ',' option signals the use of a comma for a thousands separator. For a locale aware separator, use the 'n' integer presentation type instead.

Changed in version 3.1: Added the ',' option (see also PEP 378 ).

The '_' option signals the use of an underscore for a thousands separator for floating point presentation types and for integer presentation type 'd' . For integer presentation types 'b' , 'o' , 'x' , and 'X' , underscores will be inserted every 4 digits. For other presentation types, specifying this option is an error.

Changed in version 3.6: Added the '_' option (see also PEP 515 ).

width is a decimal integer defining the minimum total field width, including any prefixes, separators, and other formatting characters. If not specified, then the field width will be determined by the content.

When no explicit alignment is given, preceding the width field by a zero ( '0' ) character enables sign-aware zero-padding for numeric types. This is equivalent to a fill character of '0' with an alignment type of '=' .

Changed in version 3.10: Preceding the width field by '0' no longer affects the default alignment for strings.

The precision is a decimal integer indicating how many digits should be displayed after the decimal point for presentation types 'f' and 'F' , or before and after the decimal point for presentation types 'g' or 'G' . For string presentation types the field indicates the maximum field size - in other words, how many characters will be used from the field content. The precision is not allowed for integer presentation types.

Finally, the type determines how the data should be presented.

The available string presentation types are:

Type Meaning 's' String format. This is the default type for strings and may be omitted. None The same as 's' .

The available integer presentation types are:

Type Meaning 'b' Binary format. Outputs the number in base 2. 'c' Character. Converts the integer to the corresponding unicode character before printing. 'd' Decimal Integer. Outputs the number in base 10. 'o' Octal format. Outputs the number in base 8. 'x' Hex format. Outputs the number in base 16, using lower-case letters for the digits above 9. 'X' Hex format. Outputs the number in base 16, using upper-case letters for the digits above 9. In case '#' is specified, the prefix '0x' will be upper-cased to '0X' as well. 'n' Number. This is the same as 'd' , except that it uses the current locale setting to insert the appropriate number separator characters. None The same as 'd' .

In addition to the above presentation types, integers can be formatted with the floating point presentation types listed below (except 'n' and None ). When doing so, float() is used to convert the integer to a floating point number before formatting.

The available presentation types for float and Decimal values are:

Type Meaning 'e' Scientific notation. For a given precision p , formats the number in scientific notation with the letter ‘e’ separating the coefficient from the exponent. The coefficient has one digit before and p digits after the decimal point, for a total of p + 1 significant digits. With no precision given, uses a precision of 6 digits after the decimal point for float , and shows all coefficient digits for Decimal . If no digits follow the decimal point, the decimal point is also removed unless the # option is used. 'E' Scientific notation. Same as 'e' except it uses an upper case ‘E’ as the separator character. 'f' Fixed-point notation. For a given precision p , formats the number as a decimal number with exactly p digits following the decimal point. With no precision given, uses a precision of 6 digits after the decimal point for float , and uses a precision large enough to show all coefficient digits for Decimal . If no digits follow the decimal point, the decimal point is also removed unless the # option is used. 'F' Fixed-point notation. Same as 'f' , but converts nan to NAN and inf to INF . 'g' General format. For a given precision p >= 1 , this rounds the number to p significant digits and then formats the result in either fixed-point format or in scientific notation, depending on its magnitude. A precision of 0 is treated as equivalent to a precision of 1 . The precise rules are as follows: suppose that the result formatted with presentation type 'e' and precision p-1 would have exponent exp . Then, if m <= exp < p , where m is -4 for floats and -6 for Decimals , the number is formatted with presentation type 'f' and precision p-1-exp . Otherwise, the number is formatted with presentation type 'e' and precision p-1 . In both cases insignificant trailing zeros are removed from the significand, and the decimal point is also removed if there are no remaining digits following it, unless the '#' option is used. With no precision given, uses a precision of 6 significant digits for float . For Decimal , the coefficient of the result is formed from the coefficient digits of the value; scientific notation is used for values smaller than 1e-6 in absolute value and values where the place value of the least significant digit is larger than 1, and fixed-point notation is used otherwise. Positive and negative infinity, positive and negative zero, and nans, are formatted as inf , -inf , 0 , -0 and nan respectively, regardless of the precision. 'G' General format. Same as 'g' except switches to 'E' if the number gets too large. The representations of infinity and NaN are uppercased, too. 'n' Number. This is the same as 'g' , except that it uses the current locale setting to insert the appropriate number separator characters. '%' Percentage. Multiplies the number by 100 and displays in fixed ( 'f' ) format, followed by a percent sign. None For float this is the same as 'g' , except that when fixed-point notation is used to format the result, it always includes at least one digit past the decimal point. The precision used is as large as needed to represent the given value faithfully. For Decimal , this is the same as either 'g' or 'G' depending on the value of context.capitals for the current decimal context. The overall effect is to match the output of str() as altered by the other format modifiers.

Format examples ¶

This section contains examples of the str.format() syntax and comparison with the old % -formatting.

In most of the cases the syntax is similar to the old % -formatting, with the addition of the {} and with : used instead of % . For example, '%03.2f' can be translated to '{:03.2f}' .

The new format syntax also supports new and different options, shown in the following examples.

Accessing arguments by position:

Accessing arguments by name:

Accessing arguments’ attributes:

Accessing arguments’ items:

Replacing %s and %r :

Aligning the text and specifying a width:

Replacing %+f , %-f , and % f and specifying a sign:

Replacing %x and %o and converting the value to different bases:

Using the comma as a thousands separator:

Expressing a percentage:

Using type-specific formatting:

Nesting arguments and more complex examples:

Template strings ¶

Template strings provide simpler string substitutions as described in PEP 292 . A primary use case for template strings is for internationalization (i18n) since in that context, the simpler syntax and functionality makes it easier to translate than other built-in string formatting facilities in Python. As an example of a library built on template strings for i18n, see the flufl.i18n package.

Template strings support $ -based substitutions, using the following rules:

$$ is an escape; it is replaced with a single $ .

$identifier names a substitution placeholder matching a mapping key of "identifier" . By default, "identifier" is restricted to any case-insensitive ASCII alphanumeric string (including underscores) that starts with an underscore or ASCII letter. The first non-identifier character after the $ character terminates this placeholder specification.

${identifier} is equivalent to $identifier . It is required when valid identifier characters follow the placeholder but are not part of the placeholder, such as "${noun}ification" .

Any other appearance of $ in the string will result in a ValueError being raised.

The string module provides a Template class that implements these rules. The methods of Template are:

The constructor takes a single argument which is the template string.

Performs the template substitution, returning a new string. mapping is any dictionary-like object with keys that match the placeholders in the template. Alternatively, you can provide keyword arguments, where the keywords are the placeholders. When both mapping and kwds are given and there are duplicates, the placeholders from kwds take precedence.

Like substitute() , except that if placeholders are missing from mapping and kwds , instead of raising a KeyError exception, the original placeholder will appear in the resulting string intact. Also, unlike with substitute() , any other appearances of the $ will simply return $ instead of raising ValueError .

While other exceptions may still occur, this method is called “safe” because it always tries to return a usable string instead of raising an exception. In another sense, safe_substitute() may be anything other than safe, since it will silently ignore malformed templates containing dangling delimiters, unmatched braces, or placeholders that are not valid Python identifiers.

Returns false if the template has invalid placeholders that will cause substitute() to raise ValueError .

Added in version 3.11.

Returns a list of the valid identifiers in the template, in the order they first appear, ignoring any invalid identifiers.

Template instances also provide one public data attribute:

This is the object passed to the constructor’s template argument. In general, you shouldn’t change it, but read-only access is not enforced.

Here is an example of how to use a Template:

Advanced usage: you can derive subclasses of Template to customize the placeholder syntax, delimiter character, or the entire regular expression used to parse template strings. To do this, you can override these class attributes:

delimiter – This is the literal string describing a placeholder introducing delimiter. The default value is $ . Note that this should not be a regular expression, as the implementation will call re.escape() on this string as needed. Note further that you cannot change the delimiter after class creation (i.e. a different delimiter must be set in the subclass’s class namespace).

idpattern – This is the regular expression describing the pattern for non-braced placeholders. The default value is the regular expression (?a:[_a-z][_a-z0-9]*) . If this is given and braceidpattern is None this pattern will also apply to braced placeholders.

Since default flags is re.IGNORECASE , pattern [a-z] can match with some non-ASCII characters. That’s why we use the local a flag here.

Changed in version 3.7: braceidpattern can be used to define separate patterns used inside and outside the braces.

braceidpattern – This is like idpattern but describes the pattern for braced placeholders. Defaults to None which means to fall back to idpattern (i.e. the same pattern is used both inside and outside braces). If given, this allows you to define different patterns for braced and unbraced placeholders.

Added in version 3.7.

flags – The regular expression flags that will be applied when compiling the regular expression used for recognizing substitutions. The default value is re.IGNORECASE . Note that re.VERBOSE will always be added to the flags, so custom idpattern s must follow conventions for verbose regular expressions.

Added in version 3.2.

Alternatively, you can provide the entire regular expression pattern by overriding the class attribute pattern . If you do this, the value must be a regular expression object with four named capturing groups. The capturing groups correspond to the rules given above, along with the invalid placeholder rule:

escaped – This group matches the escape sequence, e.g. $$ , in the default pattern.

named – This group matches the unbraced placeholder name; it should not include the delimiter in capturing group.

braced – This group matches the brace enclosed placeholder name; it should not include either the delimiter or braces in the capturing group.

invalid – This group matches any other delimiter pattern (usually a single delimiter), and it should appear last in the regular expression.

The methods on this class will raise ValueError if the pattern matches the template without one of these named groups matching.

Helper functions ¶

Split the argument into words using str.split() , capitalize each word using str.capitalize() , and join the capitalized words using str.join() . If the optional second argument sep is absent or None , runs of whitespace characters are replaced by a single space and leading and trailing whitespace are removed, otherwise sep is used to split and join the words.

Table of Contents

  • String constants
  • Custom String Formatting
  • Format Specification Mini-Language
  • Format examples
  • Template strings
  • Helper functions

Previous topic

Text Processing Services

re — Regular expression operations

  • Report a Bug
  • Show Source

All you need to know on by reference vs by value

All you need to know on by reference vs by value

by Szilard Magyar

gfKoji1a50mprGtRT9KEL4gPh6fNi6RGJ9CK

When it comes to software engineering there are quite a few misunderstood concepts and misused terms. By reference vs by value is definitely one of them.

I remember back in the day when I read up on the topic and every source I went through seemed to contradict the previous one. It took some time to get a solid grasp of it. I had no choice as it is a fundamental subject if you are a software engineer.

I ran into a nasty bug a few weeks back and decided to write an article so other people may have easier time figuring this whole thing out.

I code in Ruby on a daily basis. I also use JavaScript pretty often, so I have chosen these two languages for this presentation.

To understand all the concepts though we will use some Go and Perl examples as well.

To grasp the whole topic you have to understand 3 different things:

  • How the underlying data structures are implemented in the language (objects, primitive types, mutability,).
  • How variable assignment/copying/reassignment/comparison work

How variables are passed to functions

Underlying data types.

In Ruby there are no primitive types and everything is an object including integers and booleans.

And yes there is a TrueClass in Ruby.

These objects can be either mutable or immutable.

Immutable means there is no way you can change the object once it is created. There is just one instance for a given value with one object_id and it stays the same no matter what you do.

By default in Ruby the immutable object types are: Boolean , Numeric , nil , and Symbol .

In MRI the object_id of an object is the same as the VALUE that represents the object on the C level. For most kinds of objects this VALUE is a pointer to a location in memory where the actual object data is stored.

From now on we will use object_id and memory address interchangeably.

Let’s run some Ruby code in MRI for an immutable Symbol and a mutable String:

As you see while the symbol version keeps the same object_id for the same value, the string values belong to different memory addresses.

Unlike Ruby, JavaScript has primitive types.

They are — Boolean , null , undefined , String , and Number .

The rest of the data types go under the umbrella of Objects ( Array , Function , and Object) . There is nothing fancy here it is way more straightforward than Ruby.

Variable assignment , copying , reassignment and comparison

In Ruby every variable is just a reference to an object (since everything is an object).

When you assign a variable, it is a reference to an object not the object itself. When you copy an object b = a both variables will point to the same address.

This behavior is called copy by reference value .

Strictly speaking in Ruby and JavaScript everything is copied by value.

When it comes to objects though, the values happen to be the memory addresses of those objects. Thanks to this we can modify values that sit in those memory addresses. Again, this is called copy by reference value but most people refer to this as copy by reference.

It would be copy by reference if after reassigning a to ‘new string’, b would also point to the same address and have the same ‘new string’ value.

EDUJJ3qKxslYQaQU4HGqSfr4CJH5gwgu2e10

The same with an immutable type like Integer:

When you reassign a to the same integer, the memory address stays the same since a given integer always has the same object_id.

As you see when you compare any object to another one it is compared by value. If you wanna check out if they are the same object you have to use object_id.

Let’s see the JavaScript version:

Except the comparison — JavaScript uses by value for primitive types and by reference for objects. The behavior looks to be the same just like in Ruby.

Well, not quite.

Primitive values in JavaScript will not be shared between multiple variables . Even if you set the variables equal to each other. Every variable representing a primitive value is guaranteed to belong to a unique memory location.

This means none of the variables will ever point to the same memory address. It is also important that the value itself is stored in a physical memory location.

In our example when we declare b = a , b will point to a different memory address with the same ‘string’ value right away. So you don’t need to reassign a to point to a different memory address.

This is called copied by value since you have no access to the memory address only to the value.

-KYjFr8QIDdsGNMvjrsUac-V5KI6soar-ex3

Let’s see a better example where all this matters.

In Ruby if we modify the value that sits in the memory address then all the references that point to the address will have the same updated value:

You might think in JavaScript only the value of a would change but no. You can’t even change the original value as you don’t have direct access to the memory address.

You could say you assigned ‘x’ to a but it was assigned by value so a ’s memory address holds the value ‘x’, but you can’t change it as you have no reference to it.

The behavior of JavaScript objects and implementation are the same like Ruby’s mutable objects. Both copy be reference value.

JavaScript primitive types are copied by value. The behavior is the same like Ruby’s immutable objects which are copied by reference value .

Again, when you copy something by value it means you can’t change (mutate) the original value since there is no reference to the memory address. From the perspective of the writing code this is the same thing like having immutable entities that you can’t mutate.

If you compare Ruby and JavaScript the only data type that ‘behaves’ differently by default is String (that’s why we used String in the examples above).

In Ruby it is a mutable object and it is copied/passed by reference value while in JavaScript it is a primitive type and copied/passed by value.

When you wanna clone (not copy) an object you have to do it explicitly in both languages so you can make sure the original object won’t be modified:

It is crucial to remember this otherwise you will run into some nasty bugs when you invoke your code more than once. A good example would be a recursive function where you use the object as argument.

Another one is React (JavaScript front-end framework) where you always have to pass a new object for updating state as the comparison works based on object id.

This is faster because you don’t have to go through the object line by line to see if it has been changed.

Passing variables to functions is working the same way like copying for the same data types in most of the languages.

In JavaScript primitive types are copied and passed by value and objects are copied and passed by reference value.

I think this is the reason why people only talk about pass by value or pass by reference and never seem to mention copying. I guess they assume copying works the same way.

Now in JavaScript:

If you pass an object (not a primitive type like we did) in JavaScript to the function it works the same way like the Ruby example.

Other languages

We have already seen how copy/pass by value and copy/pass by reference value work. Now we will see what pass by reference is about and we also discover how we can change objects if we pass by value.

As I looked for pass by reference languages I couldn’t find too many and I ended up choosing Perl. Let’s see how copying works in Perl:

Well this seems to be the same just like in Ruby. I haven’t found any proof but I would say Perl is copied by reference value for String.

Now let’s check what pass by reference means:

Since Perl is passed by reference if you do a reassignment within the function it will change the original value of the memory address as well.

For pass by value language I have chosen Go as I intend to deepen my Go knowledge in the foreseeable future:

If you wanna change the value of a memory address you have to use pointers and pass around memory addresses by value. A pointer holds the memory address of a value.

The & operator generates a pointer to its operand and the * operator denotes the pointer’s underlying value. This basically means that you pass the memory address of a value with & and you set the value of a memory address with * .

How to evaluate a language:

  • Understand the underlying data types in the language. Read some specifications and play around with them. It usually boils down to primitive types and objects. Then check if those objects are mutable or immutable. Some languages use different copying/passing tactics for different data types.
  • Next step is the variable assignment, copying, reassignment and comparison. This is the most crucial part I think. Once you get this you will be able to figure out what’s going on. It helps a lot if you check the memory addresses when playing around.
  • Passing variables to functions usually is not special. It usually works the same way like copying in most languages. Once you you know how the variables are copied and reassigned you already know how they are passed to functions.

The languages we used here:

  • Go : Copied and passed by value
  • JavaScript : Primitive types are copied/passed by value, objects are copied/passed by reference value
  • Ruby : Copied and passed by reference value + mutable/immutable objects
  • Perl : Copied by reference value and passed by reference

When people say passed by reference they usually mean passed by reference value. Passing by reference value means that variables are passed around by value but those values are references to the objects .

As you saw Ruby only uses pass by reference value while JavaScript uses a mixed strategy. Still, the behavior is the same for almost all the data types due to the different implementation of the data structures.

Most of the mainstream languages are either copied and passed by value or copied and passed by reference value. For the last time: Pass by reference value is usually called pass by reference.

In general pass by value is safer as you won’t run into issues since you can’t accidentally change the original value. It is also slower to write because you have to use pointers if you want to change the objects.

It’s the same idea like with static typing vs dynamic typing — development speed at the cost of safety. As you guessed pass by value is usually a feature of lower level languages like C, Java or Go.

Pass by reference or reference value are usually used by higher level languages like JavaScript, Ruby and Python.

When you discover a new language go through the process like we did here and you will understand how it works.

This is not an easy topic and I am not sure everything is correct what I wrote here. If you think I have made some mistakes in this article, please let me know in the comments.

If this article was helpful, share it .

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

Is it possible to copy string in Python? [SOLVED]

January 9, 2024

In Python, strings are immutable sequences of characters. They can be created using single quotes ( ' ' ) or double quotes ( " " ), and even triple quotes for multi-line strings. Being immutable means that once a string is created, it cannot be changed. Any operation that seems to modify a string actually creates a new one. This feature makes strings in Python very stable but also raises the question of how to efficiently copy them when needed.

Here are different methods to copy a string in Python:

  • Assignment Operator ( = ) : Simply assigns the value of one variable to another. This creates a new reference to the same string object in memory.
  • Slicing ( [:] ) : Creates a new string by slicing the entire original string. This effectively produces a copy of the original string.
  • str() Constructor : Creates a new string using Python's built-in str() constructor , resulting in a copy of the original string.
  • copy Module's copy() Function : Generally used for mutable objects, but it can also be used to make a shallow copy of a string. Not efficient for string objects but can be used.
  • copy Module's deepcopy() Function : Intended for objects with nested structures. For strings, it behaves like copy() . Overkill for simple string copies but included for completeness.
  • Using join() Method : The join() method can join elements of an iterable (like a string) into a new string, effectively creating a copy when the original string is the iterable.
  • Using * Operator : Multiplying a string by 1 ( string * 1 ) results in a new string that is a copy of the original.
  • Built-in String Methods : Methods like str.replace() , str.upper() , and str.lower() return new strings and can be used to create copies, albeit with modifications.
  • format() Method : You can use the format() method to insert the original string into a new string template, effectively creating a copy.
  • f-Strings : By embedding the original string inside an f-string, a new string is created, which serves as a copy of the original.

Basic Ways to Copy a String in Python

When it comes to copying a string in Python, there are several straightforward methods that are not only simple but also efficient for basic use-cases. Below are some of these basic ways to achieve a Python copy string operation:

1. Assignment Operator ( = )

The assignment operator simply assigns the value of one variable to another. In Python, when you do this with a string, you are actually creating a new reference to the existing string object, rather than creating an entirely new string object.

Both original_string and copy_string will output:

Explanation and Memory Implications: Shallow Copy

Here, copy_string is a new reference pointing to the same string object as original_string . This is called a "shallow copy." Because strings are immutable in Python, having two variables pointing to the same string is usually not a problem. However, it's important to understand that no new memory is allocated for copy_string ; it points to the same location as original_string .

This is generally not an issue with strings due to their immutability, but it's good to know what's happening behind the scenes.

2. Using Slicing ( [:] )

Another way to copy a string in Python is by using slicing. The slice [:] essentially extracts all characters from the beginning to the end of the string, creating a new string. When you assign this new string to another variable, you've effectively copied the original string.

Explanation

Slicing creates a new string by copying all elements from the beginning to the end of original_string . Because a new string is generated, it will occupy its own memory space, making copy_string a distinct entity from original_string .

3. Using str() Constructor

The str() constructor can also be used to create a new string object. When you pass an existing string into str() , it returns a new string that is a copy of the original. This method is explicit, making it clear to anyone reading the code that a copy of the string is being created.

The str() constructor returns a new string that is a copy of the string passed to it. This makes it explicit that you are creating a new copy, and it occupies its own space in memory.

Advanced Ways to Copy a String

1. using copy.copy().

The copy.copy() function performs what is known as a shallow copy. It returns a new object that is a copy of the original object. However, with immutable types like strings, this method is generally overkill. It's mostly useful for mutable types like lists or dictionaries where the shallow copy creates a new object with references to the items in the original object.

2. Using  copy.deepcopy()

copy.<a href="https://www.golinuxcloud.com/python-copy-list/" title="Python copy list - deepcopy() vs copy() with examples" target="_blank" rel="noopener noreferrer">deepcopy</a>() goes a step further and performs a deep copy, creating copies of the objects that the original object references. This is useful for objects that have nested objects within them. Again, for a simple, flat, immutable type like a string, using deepcopy() is unnecessary and inefficient.

Both copy.copy() and copy.deepcopy() can be used to copy strings, but they are overkill for this purpose. They are generally intended for mutable, complex objects like lists or dictionaries that have nested structures . Since strings in Python are immutable and don't have nested structures, using these methods to copy strings is inefficient and not recommended .

3. Using  ''.join(list)

The str.join() method joins the elements in the given sequence - a list in this case. When you pass a string to join(), Python treats it like a list of characters. Thus, the join() method goes through each character in the original string and joins them together into a new string, effectively creating a copy. This method can be particularly useful if you already have to perform some form of string manipulation, as it can create a copy in the process.

The join() method joins the elements of an iterable, like a string or list, into a new string. When you use it with a string, each character is treated as an element of the iterable. By joining these characters back together, you effectively create a copy of the original string.

4. Using * Operator

The * operator, when used with strings, usually serves to repeat the given string a specified number of times. When a string is multiplied by 1 ( original_string * 1 ), the string is repeated just once, resulting in a new string that is effectively a copy of the original. This is a bit of a "hack" and not straightforward to those reading your code, but it's a valid way to create a copy nonetheless.

Multiplying a string by 1 effectively creates a new string that is a copy of the original. Although this method is not conventional, it works. The * operator usually repeats the string for as many times as the number it's multiplied by. When multiplied by 1, you get the string repeated just once, essentially creating a copy.

Built-in String Methods That Return Copies

Certain built-in string methods in Python return new string objects that are modified versions of the original string. Even though these methods are generally used for transforming strings, they effectively create new strings, serving as an indirect way to copy them. Here's how each method works:

1. Using str.replace()

The str.replace() method is designed to create a new string by replacing specified substrings in the original string. In doing so, it never alters the original string because strings are immutable in Python. Instead, a new string object is returned. In the example provided earlier, we used the replace() method to replace "world" with itself. While this keeps the string content the same, Python generates a new string object as the output. This is an indirect way to create a new string that is a copy of the original.

The str.replace() method is generally used to replace occurrences of a substring within a string. However, you can use it to create a copy by replacing a word with itself. The method returns a new string where all occurrences of the search term are replaced by the replacement term. In this example, we replace "world" with "world," which means the original string remains unchanged but a new string is created.

2. Using str.upper()

The str.upper() method works by iterating through each character in the original string and converting it to its uppercase equivalent. Like all string methods that perform transformations, str.upper() returns a new string object that contains the transformed characters. The original string remains unchanged because strings are immutable in Python. In this way, str.upper() also serves as an indirect way to copy a string, albeit with transformed content (all characters in uppercase).

original_string will output:

copy_string will output:

The str.upper() method converts all the characters in the string to uppercase and returns a new string. Even though this creates a modified string, it's still a new string object that is separate from the original.

3. Using str.lower()

Similar to str.upper() , the str.lower() method iterates through each character in the string, converting it to its lowercase equivalent. As strings are immutable, this operation doesn't modify the original string but instead returns a new string object with the transformed content. Thus, str.lower() also creates a new string object, effectively serving as another method to indirectly copy a string, but with all characters in lowercase.

Similar to str.upper() , the str.lower() method converts all characters in the string to lowercase. While the new string may differ from the original string in case, it's still a new string object separate from the original.

Pitfalls and Common Mistakes

Understanding the pitfalls and common mistakes associated with copying strings in Python can save you from a lot of bugs and inefficiencies down the road. Here are some key points:

1. Mutability vs. Immutability

How Strings are Immutable in Python

Explanation: Strings in Python are immutable, meaning once they are created, they cannot be changed. Any operation that seems to alter a string is actually creating a new string. This is different from mutable types like lists, where in-place modifications are possible.

Pitfall: Attempting to change a string in-place like this will raise an error because strings are immutable. This immutability can lead to inefficiencies if not handled properly.

2. Memory Overhead

Efficiency Considerations

Explanation: When you create a new string, Python allocates new memory for it, even if the new string has the exact same characters as the original.

Pitfall: Even though string1 , string2 , and string3 contain the same characters, they each occupy separate memory, leading to memory overhead.

3. String Concatenation

Performance Implications

Explanation: String concatenation using the + operator or += in loops creates a new string object each time, leading to a time complexity of O(n^2) for n operations.

Pitfall: In the inefficient example, the += operation creates a new string each time, leading to an O(n^2) time complexity. The efficient way utilizes the .join() method and has a time complexity of O(n), which is far better in performance-critical scenarios.

Frequently Asked Questions About Copying Strings in Python

1. Why do I need to copy a string in Python if they are immutable?

Answer: While it's true that strings are immutable in Python, copying can still be necessary when you want to work with identical yet independent string objects. This is particularly relevant in cases where the string object references need to be distinct.

2. Are all methods of copying strings equally efficient?

Answer: No, different methods have different performance implications. For example, using += for string concatenation in a loop can be significantly less efficient compared to using the join() method.

3. Does copying a string create a new memory allocation?

Answer: Yes, copying a string will generally result in a new memory allocation for the new string object, even if the string content is identical to the original.

4. What is the difference between a deep copy and a shallow copy of a string?

Answer: In the context of strings, which are immutable and flat, deep copies and shallow copies effectively do the same thing: they create a new string object with the same content. However, these terms are more relevant for mutable, nested objects like lists and dictionaries .

5. Can I copy a string by simply assigning it to a new variable?

Answer: Yes, you can assign the string to a new variable (e.g., new_string = old_string ). However, this doesn't actually create a new string in memory; it only creates a new reference to the existing string. Both variables will point to the same string object.

6. Why does Python allow multiple ways to copy a string?

Answer: Python is designed to be flexible and expressive. The various methods for copying strings are not just for the sake of copying but are also useful for a variety of other operations such as string manipulation, transformation, and more.

Summary of Methods

Throughout this article, we have discussed various methods to copy a string in Python, ranging from basic to advanced:

  • Assignment Operator
  • Using str() constructor

Advanced Ways

  • Using the copy module ( copy.copy() and copy.deepcopy() )
  • Using join() method
  • Using * operator
  • str.replace()
  • str.upper()
  • str.lower()

Best Practices

  • Use the simplest method that serves your need. For basic copying, the assignment operator or slicing is usually sufficient.
  • Understand the immutability of strings to avoid common pitfalls.
  • Be mindful of memory overhead and performance , especially in loops and performance-critical applications.
  • When manipulating and copying a string simultaneously, built-in methods like str.replace() , str.upper() , and str.lower() can be more efficient.

Additional Resources

For those interested in diving deeper into the intricacies of strings in Python, here are some recommended resources:

  • Python Official Documentation on Strings
  • Python String Methods
  • Efficient String Concatenation in Python

Deepak Prasad

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to [email protected]

Thank You for your support!!

2 thoughts on “Is it possible to copy string in Python? [SOLVED]”

None of the above is actually copying the string. check below code it will print True

a =’x’ b= ” + a print(a is b)

Correct me if I am wrong

I have updated the article, please check once and let us know if you are still facing issues

Leave a Comment Cancel reply

Save my name and email in this browser for the next time I comment.

Notify me via e-mail if anyone answers my comment.

python string assignment copy or reference

We try to offer easy-to-follow guides and tips on various topics such as Linux, Cloud Computing, Programming Languages, Ethical Hacking and much more.

Recent Comments

Popular posts, 7 tools to detect memory leaks with examples, 100+ linux commands cheat sheet & examples, tutorial: beginners guide on linux memory management, top 15 tools to monitor disk io performance with examples, overview on different disk types and disk interface types, 6 ssh authentication methods to secure connection (sshd_config), how to check security updates list & perform linux patch management rhel 6/7/8, 8 ways to prevent brute force ssh attacks in linux (centos/rhel 7).

Privacy Policy

HTML Sitemap

The Linux Code

Copying Strings in Python: An In-Depth Guide

Working with strings is central to most Python programming. Often we need to copy a string to a new variable without altering the original. But how exactly does copying strings work in Python? What are the nuances and best practices?

In this comprehensive guide, you‘ll learn:

  • The ins and outs of copying strings in Python
  • 4 main methods for duplicating a string
  • When to use each approach (with examples)
  • How string copying relates to mutability and references
  • Common pitfalls and key principles
  • Performance tradeoffs and optimizations
  • How Python‘s string handling differs from other languages

Whether you‘re a beginner looking to master strings or an experienced developer needing a quick reference, this guide has you covered! Let‘s dive in.

Why Duplicate Strings in Python?

Copying strings serves many purposes:

  • Retain the original value while modifying the copy
  • Concatenate or repeat a string multiple times
  • Pass a substring into a function without altering the source
  • Store alternate versions of a string efficiently
  • Allow values to exist in different scopes or namespaces
  • Compare strings by value instead of by reference

Strings are immutable in Python – the object can‘t be changed after creation. But assigning a string to a new variable just creates another reference to the original value.

True copying duplicates the string data into a new, distinct Python string object. This is crucial for manipulating text while preserving the original.

Let‘s explore 4 ways to deeply copy strings in Python.

1. The Assignment Operator

The simplest way to copy a string is assigning it to a new variable using = :

This allocates a new string object with the same "Hello World!" value as original .

Any changes made to original later won‘t impact copy at all since they are now distinct objects:

Assignment copies strings efficiently and is the usual default method.

Note: This creates a shallow copy. If the string was part of a complex object, the copy would reference the same nested objects.

When to Use Assignment Copying

  • General case for most string copying needs
  • Concise, readable syntax
  • Fast copying of small strings

For example:

Assignment Cons

  • Can accidentally overwrite variables
  • No protection from modifying original

Overall, assignment is the simplest way to duplicate a string. Next let‘s look at concatenation techniques.

2. Full String Concatenation

We can copy a string by concatenating it to an empty string:

This appends original to copy one character at a time, building a new string.

Let‘s compare assignment and concatenation:

Assignment is faster for small strings since it directly copies the reference. Concatenation has to rebuild the entire string from scratch.

But concatenation ensures we don‘t accidentally overwrite variables. And it can be more efficient for extremely large strings by avoiding huge temporary variables.

When to Use Concatenation

  • Avoid overwriting variables
  • Explicitly build up strings
  • Copy huge strings byte-by-byte

Concatenation Cons

  • Slower than assignment for small strings
  • More verbose syntax

Concatenation shines when we want to intentionally construct a string from parts. Next we‘ll look at a variation using loops.

3. Character-by-Character Concatenation

For very large strings, concatenating character-by-character can minimize memory usage:

This builds copy gradually rather than storing original entirely in memory.

Let‘s benchmark concatenating a 1GB string:

Character concatenation is slower but requires far less temporary memory. This pays off for huge strings.

When to Use Character Concatenation

  • Copy extremely large strings efficiently
  • Manipulate strings too big to fit in memory
  • Embed string modifications during copying

Character Cons

  • Slower for small strings
  • Loses readability compared to full concatenation

Up next we‘ll look at a shorthand string copying technique using slices.

4. String Slicing

Python‘s handy string slicing lets us quickly copy a substring or entire string:

Leaving the slice indexes blank copies original from start to end.

String slicing creates a new string object with the sliced content. Let‘s verify the copy is distinct:

Slicing is a very clean way to copy strings. But it can be less explicit than concat or assignment.

When to Use String Slicing

  • Copy substrings inline
  • Clean copies without modifying original

Slicing Cons

  • Not as clear as concat/assignment
  • Advanced syntax for beginners

String slicing is a versatile substring tool that doubles for quick full string copies too.

Strings are Immutable in Python

A key string concept is immutability – once created, a Python string can‘t be altered.

Operations like .upper() or replace() return new strings rather than modifying the original:

This makes copying strings via assignment simple. Since Python strings can‘t change, a copy points to a new underlying value.

By contrast, mutable types like lists can change state. Copying them creates a reference, not a distinct value.

Copying Strings vs Referencing Objects

When we copy a string by value, the new variable is a totally separate Python string object that happens to have the same value:

With assignment, a and b end up pointing to different string objects.

By contrast, assigning variables to each other creates a reference where both variables point to the same object:

Here changing mutable list a also changes b because they reference the same list object.

Keep this distinction in mind when copying!

Copying Strings vs Copying Objects Containing Strings

Our string copying examples directly duplicated string values.

But in practice strings are often part of larger objects like lists, dictionaries, classes, etc.

When we copy the outer object, inner strings are still referenced:

We can make deep copies of the overall object to duplicate inner strings:

Consider whether you want to copy just the string or the whole object containing it.

How Python Represents Strings

Under the hood, Python stores strings as sequences of bytes representing unicode characters (UTF-8 by default).

The key fact is that this byte sequence is immutable – Python optimizes strings by hashing and interning them.

This means each unique string value is represented by a single object. Copying a string just duplicates its reference:

Here s1 and s2 reference the same "hello" object rather than two distinct copies.

Python‘s string handling optimizes for compact storage and fast lookup. But it can produce counterintuitive scenarios when copying!

How Other Languages Handle Strings

It‘s informative to compare Python‘s strings and copying behavior to other languages:

  • Java : Strings are immutable like Python. Copying makes real duplicates.
  • C# : Strings are mutable. Copies reference same instance.
  • Ruby : Strings are mutable. Dup copies value.
  • JavaScript : Strings immutable. But strings blur with objects.

So while Python and Java strings work similarly, C#/Ruby have different behavior to be aware of.

These langauge examples demonstrate the nuances around mutability and copying semantics. Python‘s approach optimizes simplicity in most cases.

Advanced Python Libraries for Copying Strings

Python‘s built-in string copying options covered so far are simple yet versatile.

But dedicated copy libraries can extend functionality:

  • copy.deepcopy() – Fully recursive deep copies
  • strdup() – C optimized string duplicate
  • textwrap.shorten() – Smart truncation when copying

These libraries provide more control when Python‘s core string copying doesn‘t suffice.

Performance and Optimization

Let‘s briefly summarize the performance tradeoffs covered so far:

  • Assignment is fastest for small strings but risks overwriting references
  • Concatenation takes more time and temporary memory
  • Character concat minimizes memory with a loop, but is slowest

When copying large multi-gigabyte strings, character-by-character concatenation is most efficient. This incremental approach keeps memory usage low.

But for strings up to ~100KB, assignment provides the best performance without significant temporary memory overhead.

Some other optimizations include:

  • Using C extension libraries like strdup() for fast native copies
  • Avoiding intermediate representations like casting bytes to strings
  • Pre-allocating the target string size to minimize reallocations
  • Interning duplicate strings to optimize lookups

Apply these based on your use case – optimize string copying where it‘s a bottleneck, but don‘t prematurely optimize!

Best Practices for Copying Strings in Python

Let‘s recap some key best practices:

  • Use assignment as the default go-to for string copying
  • Pick concatenation when avoiding overwrites or building strings
  • Opt for character loops only for large strings to minimize memory
  • Remember strings are immutable – copying won‘t mutate the original
  • Watch for references when strings are part of mutable objects
  • Make copies explicitly – avoid assuming slices/duplicates make copies

And some pitfalls to avoid:

  • Accidentally overwriting variables with copies
  • Modifying the original string after making a copy
  • Forgetting copying strings within objects requires deepcopy()
  • Using reference assignment but expecting a distinct value

Following these reliable practices will prevent most issues when duplicating strings in Python.

Copying Strings in Python – Key Takeaways

We‘ve covered a lot of ground around duplicating strings in Python! Here are the key takeaways:

  • Use assignment to copy strings concisely, with concatenation for safe explicit copying
  • Character loops copy huge strings efficiently but are slower overall
  • Slicing provides a quick shorthand for substrings or full duplicates
  • Strings are immutable so copies point to distinct underlying data
  • Copy string values directly, use deepcopy to clone complex objects
  • Optimize with C libraries for performance, minimize temporaries
  • Stick to assignment in most cases, with concatenation/loops for specific needs

You‘re now equipped to copy strings proficiently in Python using the right approach for your situation. Happy coding!

You maybe like,

Related posts, "no module named ‘setuptools‘" – a complete troubleshooting guide.

As a Python developer, few errors are as frustrating as seeing ImportError: No module named setuptools when trying to install or run code that depends…

"numpy.float64 Cannot be Interpreted as an Integer" – A Detailed Guide to Fixing This Common NumPy Error

As a Python developer, have you ever encountered an error like this? TypeError: ‘numpy.float64‘ object cannot be interpreted as an integer If so, you‘re not…

"Unindent does not match any outer indentation level" – Common Python Indentation Error Explained

Have you encountered cryptic errors like "Unindent does not match any outer indentation level" while running your Python programs? These indentation-related errors are quite common…

10 Python List Methods to Boost Your Linux Sysadmin Skills

As a Linux system administrator, Python is an invaluable tool to have in your belt. With just a few lines of Python, you can automate…

PyCharm IDE

11 Best Python IDEs for Ubuntu in 2022

An integrated development environment (IDE) is an essential tool for Python developers. IDEs streamline the coding process with features like intelligent code completion, visual debugging,…

30 Python Scripts Examples – Python Scripts Beginners Guide

Python is one of the most popular and in-demand programming languages today. Its simple syntax, rich set of libraries and versatility make it suitable for…

techhiccups.com

Python Copy String: How, When, and What

As a Python programmer, you may have encountered situations where you need to copy a string. Whether it’s for manipulating the original string without modifying it or for creating a new string with similar content, understanding how to copy strings in Python is essential. In this article, we will explore the different ways to copy strings in Python, when to use each method, and what you need to know about them.

What is String Copying?

Before diving into the different methods of copying strings in Python, let’s first understand what string copying means. In Python, a string is an immutable object, which means that once a string is created, it cannot be changed. Therefore, when we talk about copying a string, we are essentially creating a new string object with the same content as the original string.

Method 1: Using the Assignment Operator (=)

The simplest way to copy a string in Python is by using the assignment operator (=). This method creates a new reference to the original string, so any changes made to the new string will not affect the original string. Here’s an example:

In this example, the copied_string variable is assigned the value of the original_string . Both variables now reference the same string object in memory. If we modify the copied_string , the original_string remains unchanged:

Method 2: Using the str() Function

Another way to copy a string in Python is by using the str() function. This function converts any object into a string representation. By passing the original string as an argument to the str() function, we can create a new string object with the same content. Here’s an example:

Similar to the previous method, the copied_string variable now references a new string object with the same content as the original_string . Any modifications made to the copied_string will not affect the original_string .

Method 3: Using String Slicing

String slicing is a powerful feature in Python that allows us to extract a portion of a string. By using string slicing with the full range of indices, we can effectively create a copy of the original string. Here’s an example:

In this example, the copied_string variable is assigned the value of the original_string using string slicing. The [:] notation indicates that we want to slice the entire string, effectively creating a copy of it. Any modifications made to the copied_string will not affect the original_string .

Method 4: Using the copy Module

Python provides a built-in module called copy that offers a copy() function for creating copies of objects. By importing the copy module and using the copy() function, we can create a copy of a string. Here’s an example:

In this example, the copied_string variable is assigned the value of the original_string using the copy() function from the copy module. This method creates a shallow copy of the string, meaning that any mutable objects within the string (e.g., lists) will still reference the same objects in memory.

Method 5: Using the copy Method

In addition to the copy module, Python strings also provide a built-in copy() method that creates a copy of the string. This method is similar to using the assignment operator (=) but explicitly indicates that a copy is being made. Here’s an example:

In this example, the copied_string variable is assigned the value of the original_string using the copy() method. This method creates a new string object with the same content as the original_string . Any modifications made to the copied_string will not affect the original_string .

When to Use Each Method?

Now that we have explored the different methods of copying strings in Python, let’s discuss when to use each method.

Assignment Operator (=): This method is the simplest and most commonly used for copying strings. It is suitable for most scenarios where you need to create a copy of a string without modifying the original string.

str() Function: Using the str() function is useful when you need to convert an object into a string representation and create a copy of it at the same time. This method is particularly helpful when dealing with objects that may not be strings initially.

String Slicing: String slicing is handy when you want to extract a portion of a string and create a copy of it. This method is useful when you need to manipulate a substring without modifying the original string.

copy Module: The copy module is beneficial when you want to create a shallow copy of a string, especially if the string contains mutable objects like lists. This method ensures that the copied string references the same objects in memory.

copy Method: The copy() method is similar to using the assignment operator (=) but explicitly indicates that a copy is being made. This method is useful when you want to be explicit about creating a copy of a string.

In this article, we have explored the different methods of copying strings in Python. We have learned how to use the assignment operator (=), the str() function, string slicing, the copy module, and the copy() method to create copies of strings. Each method has its own use cases and advantages, so it’s essential to choose the method that best suits your specific requirements. By understanding these different methods, you can confidently manipulate strings in Python without worrying about modifying the original string.

python string assignment copy or reference

Explore our blog at TechHiccups for insightful articles and easy-to-follow guides that help you overcome tech challenges and boost your digital know-how.

Recent Blog

  • How to Check if a Set is Empty in Python( with Example Code)
  • Python Invalid Character in Identifier(Beginner’s Guide)
  • Converting a TXT file to CSV in Python
  • For i in range(len(…)) in Python(Beginner’s Guide)
  • How to Handle “Invalid Decimal Literal” Error in Python: 7 Tips

[email protected]

  • Python Basics
  • Interview Questions
  • Python Quiz
  • Popular Packages
  • Python Projects
  • Practice Python
  • AI With Python
  • Learn Python3
  • Python Automation
  • Python Web Dev
  • DSA with Python
  • Python OOPs
  • Dictionaries

Python Lists

  • Get a list as input from user in Python
  • Python | Create list of numbers with given range
  • How to add Elements to a List in Python

Python List Access/Iteration Operations

  • Iterate over a list in Python
  • How to iterate through a nested List in Python?
  • Python | Iterate over multiple lists simultaneously
  • Iterate Over a List of Lists in Python
  • Python Program to Accessing index and value in list
  • Python | Accessing all elements at given list of indexes
  • Check if element exists in list in Python
  • Python | Check if any element in list satisfies a condition

Python List Search Operations

  • How To Find the Length of a List in Python
  • Python | Find elements of a list by indices
  • Python program to find the String in a List
  • Python | Ways to find indices of value in list
  • Python | Find most frequent element in a list

Python List Remove Operations

  • How to Remove an Item from the List in Python
  • Python | Remove given element from the list
  • Ways to remove particular List element in Python
  • Remove multiple elements from a list in Python

Python List Concatenation Operations

  • Python | Concatenate two lists element-wise
  • Merge Two Lists in Python
  • Python - Concatenate two list of lists Row-wise
  • Python program to concatenate every elements across lists
  • Python program to Concatenate all Elements of a List into a String
  • Python | Concatenate All Records
  • Python | Merge list elements
  • Python | Concatenate N consecutive elements in String list
  • Python | Merge two lists alternatively
  • Python | Union of two or more Lists

Python List Sorting and Comparison

  • Python | Sort a List according to the Length of the Elements
  • Python | Element repetition in list
  • Python - Repeat Alternate Elements in list
  • Python | Difference between two lists
  • Python | Check if two lists are identical
  • Python | Combining two sorted lists
  • Python | Cloning or Copying a list
  • Sort the values of first list using second list in Python

Python List Comprehension Operations

  • Python List Slicing
  • Python - List Comprehension
  • Python List Comprehension and Slicing

Python List Reverse Operations

  • Python List reverse()
  • Reversing a List in Python

Python Nested Lists

  • Nested List Comprehensions in Python
  • Python | Test for nested list
  • Python | How to copy a nested list
  • Python | Convert given list into nested list
  • Python | Split nested list into two lists
  • Python - Nested List to single value Tuple
  • Python | Column wise sum of nested list
  • Python | Intersection of two nested list
  • Python | Check if a nested list is a subset of another nested list

Python List Flatten Operation

  • Python - Flatten List to individual elements
  • Python | Convert a nested list into a flat list
  • Python Program to Flatten a List without using Recursion
  • Python | Sort Flatten list of list
  • Flatten A List of Lists in Python
  • Python | Split flatten String List
  • Python | Flatten given list of dictionaries
  • Python | Grouped Flattening of list
  • Python | Ways to flatten a 2D list

Python List Methods and Exercises

  • Find size of a list in Python
  • Python - Elements Lengths in List
  • Python List Exercise
  • Python List methods

Python Lists are just like dynamically sized arrays, declared in other languages (vector in C++ and ArrayList in Java). In simple language, a Python list is a collection of things, enclosed in [ ] and separated by commas. 

The list is a sequence data type which is used to store the collection of data. Tuples and String are other types of sequence data types.

Example of list in Python

Here we are creating Python List using [].

Lists are the simplest containers that are an integral part of the Python language. Lists need not be homogeneous always which makes it the most powerful tool in Python . A single list may contain DataTypes like Integers, Strings, as well as Objects. Lists are mutable, and hence, they can be altered even after their creation.

Creating a List in Python

Lists in Python can be created by just placing the sequence inside the square brackets[]. Unlike Sets , a list doesn’t need a built-in function for its creation of a list. 

Note: Unlike Sets, the list may contain mutable elements.  

Example 1: Creating a list in Python

Complexities for creating lists.

Time Complexity: O(1)

Space Complexity: O(n)

Example 2:  Creating a list with multiple distinct or duplicate elements

A list may contain duplicate values with their distinct positions and hence, multiple distinct or duplicate values can be passed as a sequence at the time of list creation.

Accessing elements from the List

In order to access the list items refer to the index number. Use the index operator [ ] to access an item in a list. The index must be an integer. Nested lists are accessed using nested indexing. 

Example 1: Accessing elements from list

Example 2: Accessing elements from a multi-dimensional list

Negative indexing

In Python, negative sequence indexes represent positions from the end of the array. Instead of having to compute the offset as in List[len(List)-3], it is enough to just write List[-3]. Negative indexing means beginning from the end, -1 refers to the last item, -2 refers to the second-last item, etc.

Complexities for Accessing elements in a Lists:

Space Complexity: O(1)

Getting the size of Python list

Python len() is used to get the length of the list.

Taking Input of a Python List

We can take the input of a list of elements as string, integer, float, etc. But the default one is a string.

Example 1: 

To know more see this .

Adding Elements to a Python List

Method 1: using append() method.

Elements can be added to the List by using the built-in append() function. Only one element at a time can be added to the list by using the append() method, for the addition of multiple elements with the append() method, loops are used. Tuples can also be added to the list with the use of the append method because tuples are immutable. Unlike Sets, Lists can also be added to the existing list with the use of the append() method.

Complexities for Adding elements in a Lists(append() method):

S pace Complexity: O(1)

Method 2: Using insert() method

append() method only works for the addition of elements at the end of the List, for the addition of elements at the desired position, insert() method is used. Unlike append() which takes only one argument, the insert() method requires two arguments(position, value). 

Complexities for Adding elements in a Lists(insert() method):

Time Complexity: O(n)

Method 3: Using extend() method

Other than append() and insert() methods, there’s one more method for the Addition of elements, extend() , this method is used to add multiple elements at the same time at the end of the list.

Note: append() and extend() methods can only add elements at the end.

Complexities for Adding elements in a Lists(extend() method):

Reversing a list, method 1:  a list can be reversed by using the reverse() method in python ., method 2: using the reversed() function:.

The reversed() function returns a reverse iterator, which can be converted to a list using the list() function.

Removing Elements from the List

Method 1: using remove() method.

Elements can be removed from the List by using the built-in remove() function but an Error arises if the element doesn’t exist in the list. Remove() method only removes one element at a time, to remove a range of elements, the iterator is used. The remove() method removes the specified item.

Note: Remove method in List will only remove the first occurrence of the searched element.

Complexities for Deleting elements in a Lists(remove() method):

Method 2: using pop() method.

pop() function can also be used to remove and return an element from the list, but by default it removes only the last element of the list, to remove an element from a specific position of the List, the index of the element is passed as an argument to the pop() method.

Complexities for Deleting elements in a Lists(pop() method):

Time Complexity: O(1)/O(n) (O(1) for removing the last element, O(n) for removing the first and middle elements)

Slicing of a List

We can get substrings and sublists using a slice. In Python List, there are multiple ways to print the whole list with all the elements, but to print a specific range of elements from the list, we use the Slice operation . 

Slice operation is performed on Lists with the use of a colon(:). 

To print elements from beginning to a range use:

To print elements from end-use:

To print elements from a specific Index till the end use 

To print the whole list in reverse order, use 

Note – To print elements of List from rear-end, use Negative Indexes. 

python-list-slicing

UNDERSTANDING SLICING OF LISTS:

  • pr[0] accesses the first item, 2.
  • pr[-4] accesses the fourth item from the end, 5.
  • pr[2:] accesses [5, 7, 11, 13], a list of items from third to last.
  • pr[:4] accesses [2, 3, 5, 7], a list of items from first to fourth.
  • pr[2:4] accesses [5, 7], a list of items from third to fifth.
  • pr[1::2] accesses [3, 7, 13], alternate items, starting from the second item.

Negative index List slicing

List comprehension.

Python List comprehensions are used for creating new lists from other iterables like tuples, strings, arrays, lists, etc. A list comprehension consists of brackets containing the expression, which is executed for each element along with the for loop to iterate over each element. 

newList = [ expression(element) for element in oldList if condition ]

Example:  

For better understanding, the above code is similar to as follows: 

Refer to the below articles to get detailed information about List Comprehension.

  • List comprehension and ord() in Python

Basic Example on Python List

  • Python program to interchange first and last elements in a list
  • Python program to swap two elements in a list
  • Python – Swap elements in String list
  • Python | Ways to find length of list
  • Maximum of two numbers in Python
  • Minimum of two numbers in Python

To Practice the basic list operation, please read this article – Python List of program

List Methods

To know more refer to this article – Python List methods

The operations mentioned above modify the list Itself.

Built-in functions with List

Do go through recent articles on Lists

Useful Links:  

  • Recent Articles on Python List
  • Python Tutorials
  • Multiple Choice Questions
  • All articles in Python Category

Please Login to comment...

Similar reads.

  • python-list

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

COMMENTS

  1. python

    On p.35 of "Python Essential Reference" by David Beazley, he first states: For immutable data such as strings, the interpreter aggressively shares objects between different parts of the program. However, later on the same page, he states . For immutable objects such as numbers and strings, this assignment effectively creates a copy.

  2. Pass by Reference in Python: Background and Best Practices

    Understanding Assignment in Python. Python's language reference for assignment statements provides the following details: If the assignment target is an identifier, or variable name, then this name is bound to the object. For example, in x = 2, x is the name and 2 is the object.

  3. Python Course #12: Pass by Assignment, Copy, Reference, and None

    This mix of pass by value and pass by reference in Python is called pass by assignment. It is essential to keep this concept always in mind when writing Python code. In the previous parts of this Python course, you have seen that it is possible to get a copy of a mutable data type by calling the .copy() function: 1. 2.

  4. Python's Assignment Operator: Write Robust Assignments

    Here, variable represents a generic Python variable, while expression represents any Python object that you can provide as a concrete value—also known as a literal—or an expression that evaluates to a value. To execute an assignment statement like the above, Python runs the following steps: Evaluate the right-hand expression to produce a concrete value or object.

  5. copy

    A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original. A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original. Two problems often exist with deep copy operations that don't exist ...

  6. Pass by reference vs value in Python

    To summarize, in pass-by-reference, the function and the caller use the same variable and object. Pass by Reference In Python Example. In this example, the function modify_list takes a list by reference. The function adds the string "Geeks" to the passed list inside the function and prints it.

  7. string

    vformat (format_string, args, kwargs) ¶. This function does the actual work of formatting. It is exposed as a separate function for cases where you want to pass in a predefined dictionary of arguments, rather than unpacking and repacking the dictionary as individual arguments using the *args and **kwargs syntax. vformat() does the work of breaking up the format string into character data and ...

  8. All you need to know on by reference vs by value

    Again, this is called copy by reference value but most people refer to this as copy by reference. It would be copy by reference if after reassigning a to 'new string', b would also point to the same address and have the same 'new string' value. When you declare b = a, a and b are pointing to the same memory address After reassigning a ...

  9. python

    Pass-by-reference in Python is quite different from the concept of pass by reference in C++/Java. Java and C#: primitive types (including string) pass by value (copy). A reference type is passed by reference (address copy), so all changes made in the parameter in the called function are visible to the caller.

  10. Python: Assignment vs Shallow Copy vs Deep Copy

    In Python 3, you can use list.copy(). However, I prefer the equivalent expression list[:] because it works in both Python 2 and 3. Shallow copy is different from assignment in that it creates a ...

  11. copy in Python (Deep Copy and Shallow Copy)

    In Python, Assignment statements do not copy objects, they create bindings between a target and an object.When we use the = operator, It only creates a new variable that shares the reference of the original object. In order to create "real copies" or "clones" of these objects, we can use the copy module in Python.. Syntax of Python Deepcopy

  12. Shallow vs Deep Copying of Python Objects

    A shallow copy means constructing a new collection object and then populating it with references to the child objects found in the original. In essence, a shallow copy is only one level deep. The copying process does not recurse and therefore won't create copies of the child objects themselves. A deep copy makes the copying process recursive.

  13. Is it possible to copy string in Python? [SOLVED]

    Here are different methods to copy a string in Python: Assignment Operator (=): Simply assigns the value of one variable to another.This creates a new reference to the same string object in memory. Slicing ([:]): Creates a new string by slicing the entire original string.This effectively produces a copy of the original string.

  14. Copying Strings in Python: An In-Depth Guide

    Working with strings is central to most Python programming. Often we need to copy a string to a new variable without altering the original. But how exactly does copying strings work in Python? What are the nuances and best practices? In this comprehensive guide, you'll learn: The ins and outs of copying strings in Python … Copying Strings in Python: An In-Depth Guide Read More »

  15. Does Python make a copy of objects on assignment?

    When you assign dict_a = dict_b, you are really copying a memory address (or pointer, if you will) from dict_b to dict_a. There is still one instance of that dictionary. To get the desired behavior, use either the dict.copy method, or use copy.deepcopy if your dict may have nested dicts or other nested objects. >>> a = {1:2}

  16. Is Python call by reference or call by value

    Python utilizes a system, which is known as "Call by Object Reference" or "Call by assignment". If you pass arguments like whole numbers, strings, or tuples to a function, the passing is like a call-by-value because you can not change the value of the immutable objects being passed to the function. Passing mutable objects can be considered as call by reference or Python pass by ...

  17. Python Copy String: How, When, and What

    The simplest way to copy a string in Python is by using the assignment operator (=). This method creates a new reference to the original string, so any changes made to the new string will not affect the original string. Here's an example: original_string = "Hello, World!" copied_string = original_string

  18. Strings and Character Data in Python

    String indexing in Python is zero-based: the first character in the string has index 0, the next has index 1, and so on. The index of the last character will be the length of the string minus one. For example, a schematic diagram of the indices of the string 'foobar' would look like this: String Indices.

  19. Python: How do I pass a string by reference?

    That being said, creating a new string will allocate a new string in memory and returning a reference for the new string, but using a currently created string will reuse the same string instance. Therefore, passing a string as a function parameter will pass it by reference, or in other words, will pass the address in memory of the string.

  20. Copy by reference or value in Python

    For example, the Python treats all basic data types e.g. single character, float, number, similarly as other programming languages. These data types are copied by default (on assignment). a = 1 b = a # a = 2, b = 1 a = 2 # output 2 1 print a, b The above code snippet illustrates the case that integers are copied by value instead of reference.

  21. assigning value in python dict (copy vs reference)

    The variable name simply points to the object in the memory. Now according to this question, >> a_dict = b_dict = c_dict = {} This creates an empty dictionary and all the variables point to this dict object. So, changing any one would be reflected in the other variables. >> a_dict["key"] = "value" #say. >> print a_dict.

  22. Python Lists

    Python List comprehensions are used for creating new lists from other iterables like tuples, strings, arrays, lists, etc. A list comprehension consists of brackets containing the expression, which is executed for each element along with the for loop to iterate over each element.