Python
  • Initial page
  • Skills & Concept
    • Function
    • Generator
    • Class
    • Asyncio
    • Interface
    • Decorator
    • Maxin
    • Abstract Base Class
    • MemoryView
  • Magic methods
    • What is Magic Methods?
  • Data Structure
    • Data Structure in Python
    • List & Tuple
    • Named Tuples
    • Slicing in Sequence
    • Queue & Dequeue
    • Ordered Dict
    • Linked list
  • Writing Test Case
    • How to write Test case
    • Testing a Flask End-point
  • Libraries
    • Flask and Gunicorn
      • Flask JWT
      • Flask Limiter
      • Flask Rest
Powered by GitBook
On this page
  • Building Lists of Lists
  • Augmented Assignment with Sequences
  • Playground

Was this helpful?

  1. Data Structure

List & Tuple

Building Lists of Lists

Method 1

  1. Create a list of three lists of three items each. Inspect the structure.

  2. Place a mark in row 1, column 2, and check the result.

board = [['_'] * 3 for i in range(3)]
print(board)
>>> [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]

board[1][2] = 'X'
print(board)
>>> [['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]
board = []
for i in range(3):
    # Each iteration builds a new row and 
    # appends it to board
    row = ['_'] * 3
    # Only row 2 is changed, as expected
    board.append(row)

Method 2

  1. The outer list is made of three references to the same inner list. While it is unchanged, all seems right.

  2. Placing a mark in row 1, column 2, reveals that all rows are aliases referring to the same object.

weird_board = [['_'] * 3] * 3
print(weird_board)
# Outer list is made of three reference to the same inner list
>>> [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
# All rows are aliases referring to the same object
weird_board[1][2] = 'O'
print(board)
>>> [['_', '_', 'O'], ['_', '_', 'O'], ['_', '_', 'O']]
row = ['_'] * 3
board = [] 
for i in range(3):
    # The same row is appended three times to board
    board.append(row)

Beware of expressions like a * n when a is a sequence containing mutable items because the result may surprise you.

For example, trying to initialize a list of lists as my_list = [ [] ]*3 will result in a list with three references to the same inner list, which is probably not what you want.

Augmented Assignment with Sequences

+= and *= operators produce very different results depending on the mutability of the target sequence

if __iadd__ is not implemented, Python falls back to calling __add__ -> a += b == a = a+b.

While a = a+b, a+b is valuated first then producing a new object, which is then bound to a

For mutable sequences, __iadd__ is implemented and that += happens in place

For immutable sequences, __iadd__ falls back to __add__

Repeated concatenation of immutable sequences is inefficient, because instead of just appending new items. The interpreter has to copy the whole target sequence to create a new one with the new items concatenated.

There is one strange situation – tuple assignment puzzler,

# What do you expect in the output
t = (1, 2, [30, 40])
t[2] += [50, 60]
# A: t becomes (1, 2, [30, 40, 50, 60])
# B: TypeError is raised with the message 'tuple' object 
#    does not support item assignment
# C: Neither
# D: Both A and B

Answer:

t = (1, 2, [30, 40])
try:
    t[2] += [50, 60]
except Exception as e:
    print(e)
print(t)

# Output:
# >>> 'tuple' object does not support item assignment
# >>> (1, 2, [30, 40, 50, 60])
  1. Putting mutable items in tuples is not a good idea

  2. Augmented assignment is not an atomic operation

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

An atomic operation must be performed entirely or not performed at all. It won't be interrupted.

Playground

PreviousData Structure in PythonNextNamed Tuples

Last updated 6 years ago

Was this helpful?