CS61A学习笔记
CS61A学习笔记 week1
是一门python课...用来速成一下python
记得很乱
~~ 绝赞更新中!~~ 开学了,下期休刊!
operators
\\ | 整除 |
---|---|
** | exp |
assignment statement
形如
a = b
a1,a2 = b1,b2
的语句,和c++不同的是无需声明变量类型。
其中第二个赋值语句,b1和b2不受当前语句的影响而改变,即先计算再赋值。
python的函数是可以通过赋值重定义的,如:
max = min
User-Defined Functions
形如
def <name>(<formal parameters>):
return <return expression>
如:
def square(x):
return mul(x , x)
def sum_squares(x, y):
return square(x) + square(y)
跟haskell一样应该是Indent-sensitive的
函数参数可以有默认值,也可以传参的时候改变默认值
None
python中的无返回值(默认返回值),type是NoneType
如:print的返回值是None,和c++里有返回值不一样。
举个例子:
print(print(1), print(2))
output:
1
2
None None
再说说print,print里不同的元素用逗号隔开,返回None。
features
使用 python -i sourse.py 来调用sourse里的函数
使用 --trace 来调试
Conditional statements
使用if、elif和else
如:
if x < 0:
return -x
elif x == 0:
return x
else:
return x
能被判定成False的如:0、None、''、False
此种语句中只要进入一个suite后面的就不会再执行了
Boolean
使用首字母大写的True和False
Boolean operators
使用 and、or、not
注意and和or都是从左到右计算,如and左边为False就返回该False值了
并且这里返回的True或者False不一定是Bool值,如 8 and 9 会返回9
and中,如果所有值都为True,返回最后一个值
or中,如果所有值都为False,也返回最后一个值
Iteration
和c++差不多使用while和for
while <expression>:
<suite>
for <variable> in <interable>:
<suite>
支持break和continue。
assert
assert <expression>,<message>
Higher-order function
这部分可以参考haskell的curry化,python的lambda表达式和高阶函数也很好用。
作业
hw01,hw02,lab00,lab01
project1(hog)
CS61A学习笔记 week2
Environments for Higher-Order Functions
简单来说frame有parent关系,找一个变量就是依次往上找
Self-Reference
一个有趣的例子:
def print_all(x):
print(x)
return print_all
print_all(1)(3)(5)
在project hog里也有类似的实现,注意和c++不同的是懒惰计算,call的时候才计算
Decorators
一种语法,用于通过高阶函数decorate一个function,即把一个函数作为高阶函数的参数变成修饰过的另一个函数
在前面加上@
def trace(fn):
def traced(*args):
print('Calling',fn,'on argument',*args)
return fn(*args)
return traced
@trace
def triple(x):
return 3*x
Recursion and Tree Recursion
就是递归
作业
hw03,lab02,lab03
CS61A学习笔记 week3
lists
>>> odds = [41,53,47,49]
>>> odds[1]
43
len
>>> len(odds)
4
append
>>> s = [2,3]
>>> t = [5,6]
>>> s.append(t)
>>> s
[2, 3, [5, 6]]
extend
>>> s = [2,3]
>>> s.extend(t)
>>> s
[2, 3, 5, 6]
+
>>> s = [2,3]
>>> a = s + t
>>> a
[2, 3, 5, 6]
slice assignment
\(s[a:b] = t\)
把在 \([a,b)\) 区间里的元素替换为 \(t\)
实测 \(a>=b\) 时替换到 \(a\) 元素之前
\(a\ b\) 默认值为序列左右两端
>>> b = a[1:]
>>> b
[3, 5, 6]
>>> s = [2,3]
>>> t = [5,6]
>>> s[0:0] = t
>>> s
[5, 6, 2, 3]
>>> s[3:] = t
>>> s
[5, 6, 2, 5, 6]
>>> s[2:] = t
>>> s
[5, 6, 5, 6]
pop
>>> s = [2,3]
>>> s.pop()
3
>>> s
[2]
>>> s.pop()
2
>>> s
[]
>>> s.pop()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: pop from empty list
remove
>>> t = [5,6,5,6]
>>> t.remove(6)
>>> t
[5, 5, 6]
containers
一个operator: in
>>> 41 in odds
True
For Statements and Ranges
可以枚举list里的元素:
for <name> in <expression>:
<suite>
只要iterable就可以For
range:连续整数,左闭右开,左端参数默认是0,iterable
可以使用list(
list comprehension
和haskell一样,不同的是要指定范围(in),语法上使用for
如:
>>> odds = [1,3,5,7,9]
>>> [x+1 for x in odds]
[2,4,6,8,10]
>>> [x+1 for x in odds if 25 % x ==0]
[2,6]
注意它的type是generator
strings
一个函数:exec()用于把string当作命令执行
string也可以当作字符数组访问,下标从0开始
string的list比较特殊,in操作符可以判断substring
Dictionary
对key值和value值建立映射,内置一些函数:
内部实现应该是hashtable
numerals = {'I': 1, 'V': 5, 'X': 10}
>>> numerals.keys()
dict_keys(['I', 'V', 'X'])
>>> numerals.values()
dict_values([1, 5, 10])
>>> numerals.items()
dict_items([('I', 1), ('V', 5), ('X', 10)])
>>> items = [('I', 1), ('V', 5), ('X', 10)]
>>> dict(items)
{'I': 1, 'V': 5, 'X': 10}
>>> 'X' in numerals
True
>>> numerals.get('X')
10
>>> numerals.get('X-ray')
>>> numerals.get('X-ray',0) # 默认值
0
# dictionary comprehension
>>> squares = {x:x*x for x in range(10)}
>>> squares[7]
49
>>> {[1]:2}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Raising Exceptions
使用 python -0 打开调试模式,忽略所有assert
也可以使用raise:
raise <expression>
raise TypeError('111!')
#还有NameError,KeyError,RuntimeError
Try Statements
try:
<try suite>
except <exception class> as <name>:
<except suite>
...
如果 try suite 发生
套娃的try在内层处理成功了就不会进入外层except
Reduce
相当于haskell的foldl
用法:
from functools import reduce
reduce(<function>,<list>,<initial_element>)
reduce(mul,[1,2,3],1)
Processing Container Values
一些自带函数:sum,max(可选key函数),all(iterable里所有元素都为True返回True),any(同理)
>>> max(range(10),key = lambda x: 7-(x-4)*(x-2))
3
# 即keyfunc(x)最大的x
Trees
用python的强强list来储存树结构
即第0个元素是根结点元素,后面每个元素是一个子树(也是list)
作业还只准你用它封装的东西,就很蠢。
Object
有关String的一些函数和method:
ord(s) #ascii
s.upper()
s.lower()
s.swapcase()
Mutation Operations
list 和 dictionary 是 mutable type,可以mutation
包括给 function 传参一个list或者dictionary,在function里改变这个参数,在外面也会改变(相当于c++引用传参)
Tuples
元组,非mutable的sequence
Identity & Equality
a is b # identity,是否bound到相同的元素
a == b # Equality,值是否相同
作业
lab04,lab05,hw04
project2(cat)
CS61A学习笔记 week4
nonlocal
在local frame里用 nonlocal 声明parent frame里的变量,把这个变量bound到nonlocal frame里
nonlocal <name>
python 是把声明变量和变量赋值都放在 assignment 写法里的,注意二者的区别
另外就是mutable的类型(list、dictionary): 不需要nonlocal也可以直接在local frame用parent frame的变量
Iterator
iter(iterable) : return an iterator
next(iterator) : return the next element in an iterator
dictionary有不同的iterators:
k = iter(d.keys())
v = iter(d.values())
i = iter(d.items())
如果dictionary改变了那么之前的iterator会失效。
For Statements
for一个iterator的时候,会枚举当前元素以及之后的所有元素
Built-in Iterator Functions
map,filter,zip: 和haskell的定义相同
但是注意这些函数得到的是一个iterator,并且计算是lazy的,只有把iterator遍历一遍才会计算。
reversed,list,tuple,sorted: 顾名思义,把iterator变成各种形式
next(incr, v) 当StopIteration时返回v
generator
属于iterator的一种
使用关键字 yeild
一个generator function可以返回多个值,用yeild标出,最后返回一个iterator包含所有返回值。
注意generator function的计算也是lazy的。
一种方便的写法:要得到一堆结果的时候可以全部yeild出来再用list转换
利用这个方法python也是可以得到无穷序列的
yeild from statement
for x in a:
yield x
等价于
yeild from a
作业
lab06,lab07,hw05
midterm
CS61A学习笔记 week5
Class Statements
class <name>:
<suite>
其中suite用def定义method
>>> class Account:
def __init__(self, account_holder):
self.balance = 0
self.holder = account_holder
其中__init__
是类似关键字的初始化函数,包含一个self和一些可选参数。
另一个关键字是__repr__
,直接引用一个实例时的返回值。
Method
在class里定义其他函数:
def deposit(self, amount):
self.balance += amount
return self.balance
Attributes
built-in functions:
>>> getattr(john, 'balance') # = john.balance
>>> hasattr(john, 'balance') # check attrribute
True
Class里的Attributes可以是function,也可以是简单的值。
Methods and Functions
Object + Function = Bound method, 即把Object传入一个Class里的Function的self参数就得到了method
>>> Account.deposit(tom_account,1001) # <class 'function'>
1011
>>> tom_account.deposit(1000) # <class 'method'>
2011
Class Attributes
也可以开class里的全局变量:
class Account:
interest = 0.02
def __init__(self, account_holder):
self.balance = 0
self.holder = account_holder
...
...
>>> tom_account.interest
0.02
>>> jim_account.interest
0.02
instance attribute:self.name(在init里声明或者在外面assign)
class的这种变量也可以被self拿来用(self.interest)
Attribute Assignment
注意是Class attribute 还是 instance attribute
比较重要的是dot表达式的求值顺序:<expresion>.<name>
- 计算左侧表达式,得到object
- 如果左侧实例(instance)有一个这样的attribute,返回值
- 否则在对应的class里去找,返回值
- 如果找到的是一个函数,则返回bound method
那么如果当前实例和class里有重名attribute则优先返回实例里的。
对instance attribute的assignment不对class有影响。
Inheritance
从一个class继承到另一个class:
class <name>(<base class>):
<suite>
找name也是一级一级往上找的
注意self是哪个instance的
super(): 另一种访问上一级class (base class) 的方式
Multiple Inheritance
attribute名称冲突时优先选在继承树上近的那个
John老师认为不好用(救世啊!)
Linked Lists
链表,作为class的例子
isinstance
:判断是否为class的实例
@property
:把method转化为attribute,不加括号可以直接调用
@<attribute>.setter
: 用于已经@property的method,可以进行赋值等操作
Tree class
另一个例子
Memoization
python的一种记忆化写法:使用dictionary和decorator:
def memo(f):
cache = {}
def memoized(n):
if n not in cache:
cache[n] = f(n)
return cache[n]
return memoized
Exponentiation
快速幂
String Representations
class里的关键字__str__
和__repr__
__repr__
返回一个python表达式(string),其运行的结果是object本身(eval(repr(object)) == object)
__str__
返回一个更容易被人类理解的表达式,print出来的就是__str__
Implementing repr and str
instance attribute called __repr__
or __str__
is ignored!
Only class attributes are found
def repr(x):
return type(x).__repr__(x)
注意,即使你在init里定义 self.__repr__
也会被忽略
如果一个class没有定义str,会用repr作为代替
Special Method Names
再总结一波关键字!
__add__
: 调用+,左结合
__radd__
: +右结合
__bool__
__float__
: 强制转换
Example: Reading Files
使用open来打开文件
Sets
python的内置set
>>> s = {'one','two','three','four','four'}
>>> 'three' in s
True
>>> len(s)
4
>>> s.union({'one','five'}) # 并
{'three','five','one','four','two'}
>>> s.intersection({'six','five','four','three'})# 交
{'three','four'}
>>> s
{'three','one','four','two'} #union和intersection不改变s
>>> s.add(<object>)
>>> s.update(<tuple,list,dict>)
>>> s.discard(<object>)
>>> s.clear()
*args and **kwargs
*args: 剩下的无名参数(args是一个tuple)
*kwargs: 剩下的关键字参数(kwargs是一个dictionary)
如:
>>> def pr(*args,**kwargs):
print('args=',args)
print('kwargs=',kwargs)
>>> pr(1,2,3,a=2,b=4,c=6)
args= (1,2,3)
kwargs= {'a':2,'b':4,'c':6}
注意args和kwargs不是关键字,起作用的是前面几个星号,名称可以改变
星号
单星号:可以把list/tuple/dict的元素“取出来”,形成多个值,其中dict取键值
双星号:取dict中的value
还有就是上面args的用法
作业
lab08,lab09,hw06
project3(Ants)(big big project!)
CS61A学习笔记 week6
scheme
新语言!好像是project4要用python写一个interpreter!
> (Integer? 1)
#t
> (+ 1 2)
3
Special Forms
- If expression:
(if <predicate> <consequent> <alternative>)
- And and or:
(and <e1>...<en>),or(<e1>...<en>)
- Binding symbols:
define <symbol> <expression>
- New procedures:
define (<symbol> <formal parameters>) <body>
Lambda Expressions
(lambda (<formal-parameters>) <body>)
Lists
链表
cons: constructor
car: 返回第一个元素
cdr: 返回剩下的元素
nil: empty list
> (cons 1 (cons 2 nil))
(1 2)
Symbolic Programming
可以quote一个元素,不需要bound到value也可以使用变量:
> 'a
a
> (quote a)
a
> (list 1 'a)
(1 a)
> (list 1 a)
Error
Interpreters
表达式树那一套... 直接做project得了
Tail recursion
好像就是要在函数/if语句的末尾进行递归,不需要在递归完成后进行其他操作,这样编译器会优化栈空间
Programs as Data
大概意思是scheme所有的代码都是list
Macros
begin: eval一系列代码(死去的monad记忆突然开始攻击我)
macro:自定义special form,使用define-macro定义的函数不会先eval,相当于把参数先quote起来
主要方法是使用单引号在文本的层次上“模拟”出程序语句
作业
lab10(刚好10个question)
lab11
hw07
project4(scheme)