Python

Table of Contents

__str__() vs __repr__():

  • __str__(): for human to read
  • __repr__(): for developer to recreate the object

Assignment is special

Assignment is pointing the name to a new object

While most of the operators in python are just syntactic sugar for member function calls, such as +, -, [], etc.

= does not always mean assignment.

+=

In fact, n+=1 will always prefer calling n.__iadd__(1). If it is not defined, then it will call n=n.__add__(1), which will trigger an assingment.

a[:3] = 2

this is syntactic sugar for a.__setitem__(slice(None, 3, None), 2).

Python function always does passing by reference

However, sometimes it feels like passing by value. This illution is caused by something else. For example,

Assignment is pointing the name to a new object

def add_one(n):
    n += 1
a = 1
add_one(a)
assert a == 1
# a is still 1 here.

In this case, a is passed into add_one by ref, however, n+=1 is n=n.__add__(1) in this case, and it points n to a different object.

= does not always mean assignment

def add_one(n):
    n += 1
a = np.ones((1))
add_one(a)
assert np.all(a == np.array([2]))

In this case, n+=1 is calling n.__iadd__(1), and an inplace add is performed, it is different from n=n+1.

b=a[1:3]

If a is np.ndarray or pd.DataFrame, b is a view.

If a is a list, b is (1 level) shallow copy.

It feels like sometimes assignment gives you a reference. Sometimes it gives you a copy. In fact, the trick is done in [1:3], namely slicing. For a np.ndarray and pd.DataFrame, slicing returns a view (like a reference), while for a list, slicing returns a shallow copy.