仅用作个人学习记录
Reference:https://inst.eecs.berkeley.edu/~cs61a
List
List creation
从头建立列表:
a = []
b = [0, 1, 2, 3]
利用已有的列表创建列表:
c = b + [20, 30]
d = c[:]
e = list(c)
e2 = e
列表相加、切片和list()构造都返回一个新的列表,并不会改变参数列表。故都是非破坏性操作。
注意在列表的操作中+=
并不是一个语法糖,即b = b + [20, 30]
和b += [20, 30]
是不同的。+=
是破坏性操作。
List mutation
对切片赋值是破坏性操作。
L = [1, 2, 3, 4, 5]
L[2] = 6
L[1:3] = [9, 8]
L[2:4] = [] # Deleting elements
L[1:1] = [2, 3, 4, 5] # Inserting elements
L[len(L):] = [10, 11] # Appending
L[0:0] = range(-3, 0) # Prepending
List methods
list 是一个对象,对象有方法,方法就是在对象上调用函数。
append 和 extend
append()
添加单个元素到列表中,单个元素、列表都可作为参数。
extend()
添加一个列表中的所有元素到已有列表。相当于+=
。
extend()
接受列表作为参数。
s = [2, 3]
s.extend(4) # TypeError: 'int' object is not iterable
s.extend([4])
append
和extend
都是破坏性操作。使用id
可以发现,使用append
和extend
前后地址不变。
pop 和 remove
pop()
移除列表最后一个元素,并将该元素返回。
pop
也可接受参数,移除索引值为参数的值并返回该值。
remove()
移除列表中第一个与参数相等的元素。
注意若列表中没有值与参数想匹配,则会引发异常。
s = [6, 7, 4, 8, 4]
try:
s.remove(1)
except:
print("ValueError: list.remove(x): x not in list")
显然,pop
和remove
都是破坏性操作。
Equality and Identity
Equality:exp0 ==exp1,==
判断两个对象的值是否相等。
如果 exp0 和 exp1都包含相等数值的对象,则结果为True。
Identity :exp1 is exp1,is
判断两个对象是否完全相等。
如果 exp0 和 exp1为同一个对象,则结果为True。
>>> list1 = [1,2,3]
>>> list2 = [1,2,3]
>>> list1 == list2
True
>>> list1 is list2
False
相同的对象总是有相同的值。
>>> list1 = [1,2,3]
>>> list2 = list1
>>> list1 is list2
True
>>> list1 == list2
True
一般何时使用 is:
-
判断一个值是否为空,a is none
-
判断两个对象的类型是否一致,type(a) is type(b)
在处理数字和字符串时不要使用is
,而是使用==
。对于较小的数字和字符串时python会优化内存,这使我们会被is
误导。
>>> a = 100
>>> b = 100
>>> a is b
True
>>> a = 1000000
>>> b = 1000000
>>> a is b
False
Scopes
Names inside local scopes
attendees = []
def mark_attendance(name):
attendees.append(name)
print("In attendance:", attendees)
mark_attendance("Emily")
mark_attendance("Cristiano")
mark_attendance("Samantha")
attendees = []
def mark_attendance(name):
attendees = attendees + [name] # UnboundLocalError
print("In attendance:", attendees)
mark_attendance("Emily")
mark_attendance("Cristiano")
mark_attendance("Samantha")
第二个程序不可行,在执行attendees = attendees + [name]
时,并未在本地的环境帧中找到attendees
,python 知道要在当前环境下创建一个新的名称attendees
,并计算值与其绑定。而在计算attendees + [name]
时,发现attendees
并未赋值。出现错误referenced before assignment
。
解决办法1:
def mark_attendance(name):
global attendees
attendees = attendees + [name] # UnboundLocalError
print("In attendance:", attendees)
但使用global
并不是一个好习惯,在函数内部重新分配全局变量会导致代码更加脆弱和不可预测。
解决办法2:
attendees = []
def mark_attendance(attendees, name):
attendees = attendees + [name] # UnboundLocalError
print("In attendance:", attendees)
return attendees
mark_attendance(attendees, "Emily")
mark_attendance(attendees, "Cristiano")
mark_attendance(attendees, "Samantha")
Names inside nested scopes
def make_tracker(class_name):
attendees = []
def track_attendance(name):
attendees.append(name)
print(class_name, ": ", attendees)
return track_attendance
tracker = make_tracker("CS61A")
tracker("Emily")
tracker("Cristiano")
tracker("Julian")
def make_counter(start):
current = start
def count():
current = current + 1 # UnboundLocalError
print("Count:", current)
return count
counter = make_counter(30)
counter()
counter()
counter()
解决办法1:
def make_counter(start):
current = start
def count():
nonlocal current
current = current + 1
print("Count:", current)
return count
counter = make_counter(30)
counter()
counter()
counter()
同样使用nonlocal
并不是一个好习惯。nonlocal
关键字仅添加到 Python 3,因此大多数可能使用它的代码都可以用更 Pythonic 的方式完成。
def make_counter(start):
current = start
while True:
current = current + 1
print("Count:", current)
yield
counter = make_counter(30)
next(counter)
next(counter)