angular的lib & npm link用得太郁闷,随便看点不相关的课程快乐一下。
 
课程资源: 课程资源  视频地址: 视频地址 
视频是2016年版的,比较新,所以主要一视频为主。入门课程,看看能不能用来放松心情。
主要的教学内容:knowledge of concepts,programming skill, problem solving。
What is computation what does a computer do 基础: 执行计算,存储结果
计算的类型: 语言内建 和 通过程序员定义的
计算机只知道你告诉他们的东西。
types of knowledge 
computers are machines 类型: 固定程序计算机(e.g.计算器) 和 存储程序计算机(可以执行指令)
 
stored program computer 
Basic Primitives 
图灵说使用6个元语你就可以计算任何东西了(move left, move right, read, write, scan, do nothing)。 
现代的编程语言有着更多的方便的元语集合。 
可以通过抽象方法来创建新的元语。 
任何可以用一门语言计算得出的,也一定可以用另一门语言计算得出。 
 
Creating Recipes 
一门编程语言提供了一个元语操作符的集合 
编程语言中,表达式是复杂但合理的元语集合 
编程语言中,表单时和计算有价值和意义 
 
Aspect Of Language 
元语结构
英语:单词 
编程语言: numbers,strings,simple operators 
 
 
语法
英语: “cat dog boy” 无效语法 – “cat hugs boy” 有效语法 
编程语言: “hi”5 无效语法 – 3.2*5 有效语法 
 
 
静态语义(有意义的有效语法)
英语:”I are hungry”(有效语法但静态语义错误) 
programming language: 3.2*5 | 3+”hi”(有效语法但静态语义错误) 
 
 
 
Aspects Of Language 语义,英语中可能一句话有多个意思,但是编程语言中只有一个意思并且可能不是程序员的本意。
Where Things Go Wrong 
Python Programs 
程序是定义和命令的序列 
命令告诉解释器做什么 
可以再shell中或者文件中编写 
 
Objects 
程序操作数据对象 
对象有一个类型,定义了程序可以对它们做哪些是(人,可以走路…) 
两种对象
scalar(标量对象),在python中的基本对象(6) 
non-scalar(非标量对象),具有一些内部结构的对象([5,6,7]) 
 
 
 
Scalar Objects int,float,bool,NoneType
可以用type()来看对象的类型。
Type Conversions(CAST) 对象之间可以相互转化
Printing To Console print()
Expressions 
结合对象和操作符组成表达式 
一个表达式有一个值(有类型) 
一个简单的表达式语法 (<object><operator><object>) 
 
Operators On Ints And Floats +,-,*,/,%,**
Binding Variables And Values 
等号把一个值赋值给一个变量名 
值存储在电脑内存中 
赋值操作把名字和值绑定 
与变量名相关联的值可以通过调用变量名重新获取 
 
Abstracting Expressions 为什么要把表达式的值给一个名字?
Programming vs Math 编程中,你不能“solve for x”(你要告诉计算机怎么做)(等号左边一定是变量,右边一定是表达式,和数学不同)
Changing Bindings 
通过重新赋值语句可以重新绑定变量名 
先前的值可能还存贮在内存中,但是失去操作(可能最后被垃圾收集器处理) 
重新计算之后值才会变化 
 
Shell vs. Editor 
(just an execise)
Python vs. Math 
(just an execise)
Bindings 
(just an execise)
Branching and Iteration Strings 
字母,特殊字符,空格,数字 
被包在双引号或单引号中 
连接的字符串 
进行一些字符串的在python文档中被定义的运算符 
 
可以打印引号里的一切 
用户打一些东西然后敲击enter 
把值绑定给变量(text = input(“Type anything…”)) 
返回一个字符串,如果要作用于数字的话,要类型转化(num = int(input(“Type a number…”))) 
 
Comparision Operations On int, float, string 
, >=, <, <=, ==, !=
 
Logic Operators On bools not, and, or
Control Flow - Branching if, if…else…, if…elif…else
使用缩进来表示代码块
Indentation 缩进在Python中很关键
可以嵌套使用分支结构
= VS == 赋值和等价
Control Flow: while Loops while, for…in…, for…in range(start, stop, step)
break Statement 
立刻退出它所在的循环 
跳过代码块中剩下的表达式 
!只退出最内层的循环 
 
for VS while Loops 
for loops 
while loops  
 
 
 知道迭代次数 
循环无限次数 
 
 can break 
can break 
 
 使用计数器 
使用计数器必须再循环前初始化,再循环内部增加 
 
 可以用while loop重写 
while loop不一定可以用for loop 
 
 
Strings 
(just an execise)
Comparisons 
(just an execise)
Branching 
(just an execise)
While Loops 
(just an execise)
For Loops 
(just an execise)
String Manipulation, Guess and Check, Approximations, Bisection Strings 
把它看作是一个区分大小写的字符序列 
可以用 ==,>,<,等来比较字符串 
可以使用len()函数来获取被括号包围的字符串的长度 
方括号被用来执行一个字符串的序号来获得在这个序号位置的值(python中负数的索引表示倒数第几个) 
 
切片 
For Loops Recap 
1 2 3 4 for  var in  range(4 ):  <expression>    
 
range是一种数字迭代的方式,但是循环变量可以迭代任何一系列的值,不仅仅是数字 
 
Strings And Loops 1 2 3 4 5 s = "abcdefgh"  for  char in  s:  if  char == 'i'  or  char == 'u'      print("There is an i or u" ) 
 
Code Example: Robot Cheerleaders 
Algorithms Guess-And-Check 猜想与验证
Approximate Solusions 
比较好的解决方法 
以一个猜测开始,然后以一个很小的值递增 
如果满足(条件,e.g. sth >= epsilon),就一直猜测下去 
减小递增值会减慢程序运行,增加epsilon会让结果减少精确度 
 
Bisection Search(二分法) 
Bisection Search Convergence 
搜索空间:
第一次猜想:N/2 
第二次猜想:N/4 
第k次猜想:N/2的k次方 
 
 
以$\log_2(N)$速度收敛 
二分查找法适用于函数的值在输入值的单调区间中的情况(范围不对肯定找不到呀) 
 
Decomposition,Abstraction,Functions Good Programming 
代码不是写的越多就代表质量好 
用功能的数量来衡量好的程序员 
介绍functions 
理解分解和抽象的机制 
 
Create Structure With Decomposition 
在投影的例子中,分解体现在分离的设备 
在编程中,分解体现在将代码划分为模块
独立的 
用来分解代码 
为了可以复用 
使代码有组织 
是代码清晰 
 
 
在这节课中,我们用functions实现分解 
在接下来的几周,我们用classes实现分解 
 
Supress Details With Abstraction 
投影仪的例子中,设备重要的是知道如何使用它,而不是知道如何制造它 
在编程中,把一份碎片的代码认为是一个黑盒
不能看到细节 
不需要看到细节 
不想要看到细节 
隐藏冗长的细节 
 
 
用函数规格或者文档字符串来获取抽象 
 
Functions 
functions是可重用的代码块 
在程序中,只有当functions被调用时,它们才会运行 
function的特征:
有一个名字 
有0个或多个参数 
有文档字符串(可选但推荐) 
有函数体 
returns something 
 
 
 
How To Write And Call/Invoke A Function 1 2 3 4 5 6 7 8 9 def  is_even (i) :  """    Input: i, a positive int   Returns True if i is even, otherwise False   """   print("inside is_even" )   return  i%2  == 0  is_even(2 ) 
 
Variable Scope 
形参在函数调用的时候绑定实参的值 
进入函数的时候创建了一个新的作用域 
作用域是名称到对象的映射 
 
One Warning If No Return Statement 
如果没有显示的给出return,python会return none 
none表示缺了一个值 
 
Functions As Arguments 
1 2 3 4 5 6 7 8 9 10 11 def  func_a () :  print  'inside func_a'  def  func_b (y) :  print  'inside func_b'    return  y def  func_c (z) :  print  'inside func_c'    return  z() print  func_a()print  5  + func_b(2 )print  func_c(func_a)
 
Scope Example 
在函数里,可以获得函数外的变量 
在函数里,不能改变在函数外定义的变量——可以使用全局变量,但是不赞成 
 
Harder Scope Example pythontutor 
一个详细展示每一步的作用域的软件,还有其他语言的版本
Scope Details 
Function calls 
Functions as Arguments 
Tuples,Lists,Aliasing,Mutability,and Cloning Today 
已经介绍过许多种类型:int,float,bool,string 
介绍新的复合数据类型
 
别名的概念 
易变性概念 
克隆的概念 
 
Tuples 
一个元素的有序集合,可以混合元素类型 
不能改变元素的值(和字符串一致,不可变性) 
用圆括号表示 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 te = () t = (2 , "mit" , 3 ) t[0 ] (2 , "mit" , 3 ) + (5 , 6 ) t[1 :2 ] len(t) t[1 ] = 4  
 
 
1 2 3 4 5 def  quotient_and_remainder (x, y) :  q = x // y   r = x % y   return  (q, r) (quot, rem) = quotient_and_remainder(4 , 5 ) 
 
Manipulating Tuples–aTuple:((), (), ()) 
Lists 
一个元素的有序集合,可以混合元素类型 
可以改变元素的值(可变性) 
用方括号表示 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 a_list = [] L = [2 , 'a' , 4 , [1 ,2 ]] len(L) L[0 ] L[2 ]+1  L[3 ] L[4 ] i = 2  L[i - 1 ] 
 
Changing Elements 
lists是可变的 
赋值某一下标的某一元素改变了值 L = [2, 1, 3] L[1] = 5 L 现在等于 [2, 5, 3],注意这是同一个对象(和之前在内存中指向一个新的对象是不同的) 
 
Iterating Over A List 
Operations On Lists - ADD 
在列表尾部加上元素使用L.append(element) 
改变了列表 
 
1 2 3 L = [2 , 1 , 3 ] L.append(5 ) 
 
What is the dot? 
1 2 3 4 5 6 L1 = [2 , 1 , 3 ] L2 = [4 , 5 , 6 ] L3 = L1 + L2 L1.extend([0 , 6 ]) 
 
Operations On Lists - Remove 
使用del(L[index])来删除指定下标的元素 
使用L.pop()来移除列表最后的元素,返回被移除的列表 
使用L.remove(element)来移除指定元素
找到这个元素并移除 
如果出现多次,移除第一次出现的 
如果列表中不存在这个元素,返回error 
 
 
 
Convert Lists To Strings And Back 
使用list(s)来将字符串转化为数组,返回一个数组包含每一个s中的字符 
使用s.split()按字符来分隔字符串,如果没有传入参数,那就按照空格来分隔 
使用’’.join(L)来把数组元素编程字符串,引号中可以设置一个字符来加入每个元素中间组成字符串 
 
Other List Operations 
sort() & sorted() 
reverse() 
… 
 
1 2 3 4 5 6 7 L = [9 , 6 , 0 , 3 ] sorted(L) L.sort() L.reverse() 
 
An Analogy 一个别名的例子。别名拥有的属性是一致的。
Aliases 
hot加入是warm的别名——改变一个就会改变另一个 
append()有副作用 
 
Cloning A List 
使用chill = cool[:]创建一个新的list并且拷贝list中的每个元素 
 
Sorting List  一个显示直接赋值和拷贝倒一个新的数组中的区别的例子
Lists Of Lists Of Lists 
Mutation And Iteration Try This In Python Tutor 
避免在迭代数组的时候的改变数组
在循环中,数组的索引计数器、出事长度并不会因为你的删除等操作而改变 
正确的做法是先进行副本拷贝 
 
 
 
1 2 3 4 5 def  remove_dups (L1, L2) :  L1_copy = L1[:]   for  e in  L1_copy:     if  e in  L2:       L1.remove(e) 
 
Tuples 
Simple Lists 
List Operations 
List Aliasing/Mutation  
Recursion and Dictionaries Recursion 递归就是以自我相似的方式重复项目的过程
What Is Recursion 在算法上,是一种分而治之和减而治之的问题解决方案。
语义上来说,函数调用它本身的一种编程技术
在编程中,不要得到无限循环
确保至少有一个或多个容易解决的基本案例 
为了简化大的问题的输入,必须用一些别的输入来解决相同的问题 
 
 
 
Iterative Algorithms So Far 
循环结构导致迭代的算法 
可以通过循环,在每一次迭代中捕获更新一系列状态变量的计算 
 
Multiplication-Iterative Solution 
a*b相当于a与自身相加b次 
通过以下方式捕获状态:
一个迭代数字i从b开始,i<- i-1,到0停止 
一个计算值result,result<-result+a 
 
 
 
1 2 3 4 5 6 def  mult_iter (a, b) :    result = 0    while  b > 0 :     result += a     b -= 1    return  result 
 
Multiplication-Recursive Solution 
循环步骤
 
基础案例
把问题减小到有一个基本案例是可以被直接解决的 
while b=1, a*b=a 
 
 
 
1 2 3 4 5 def  mult (a, b) :  if  b == 1 :     return  a   else      return  a + mult(a, b-1 ) 
 
Factorial n! = n*(n-1)*(n-2)*(n-3)*...*1
Recursive Function Scope Example 
Some Observations 
使用同一个变量名,但是他们是不同作用域中的不同对象
 
每一次递归调用,意味着一个函数创建了他自己的作用域 
作用域中绑定的变量不被递归调用改变 
一旦函数返回值了,控制流回返回到先前的作用域 
 
Iteration vs. Recursion 1 2 3 4 5 6 7 8 9 10 11 def  factorial_iter (n) :  prod = 1    for  i in  range(1 , n+1 ):     prod *= i   return  prod def  factorial (n) :  if  n==1 :     return  1    else :     return  n*factorial(n-1 ) 
 
递归更简单,更直观易懂 
递归对于程序员的观点来说更有效率 
递归对于计算机的观点来说并不是更有效率 
 
Inductive Reasoning 
我们怎么知道我们的递归代码会起作用? 
循环的版本,有循环终止条件 
递归的版本,有递归终止条件,知道基本的案例返回结果而不是调用 
 
数学归纳法的思想
Example Of Induction 0+1+2+3+…+n = (n(n+1))/2
证明: 如果n=0,0 = (0(0+1))/2,true 假设n = k, 0+1+2+…+k = (k(k+1))/2,true 那么 0+1+2+…+k+(k+1) = ((k+1)(k+2))/2, true 所以,得证
Relevance To Code 
1 2 3 4 5 6 7 def  mult (a, b) :  if  b ==1 :          return  a    else :          return  a + mult(a, b-1 ) 
 
另一个递归的例子:河内塔问题 1 2 3 4 5 6 7 8 9 10 11 def  printMove (fr, to) :  print('move from'  + str(fr) + ' to '  + str(to)) def  Towers (n, fr, to, spare) :  if  n == 1 :     printMove(fr, to)   else :          Towers(n-1 , fr, spare, to)     Towers(1 , fr, to, spare)     Towers(n-1 , spare, to, fr) 
 
Recursion With Multiple Base Cases 
斐波那契数字:兔子问题(两个月后才有繁衍能力)
Month | Females ——— | ———— 0 | 1 (小兔子还没繁衍能力,还是1个) 1 | 1  (小兔子还没繁衍能力,还是1个) 2 | 2 (1个小兔子,1个成年兔子) 3 | 3 (2个小兔子,1个成年兔子) 4 | 5 (3个小兔子,2个成年兔子) … | … 
females(n) = females(n-1) + females(n-2)
在第n个月的时候,females(n-2)个已经成熟的兔子可以生出小兔子,females(n-1)本来的兔子个数
 
和河内塔问题不同,这种递归有两个参数了
 
 
1 2 3 4 5 def  fib (x) :  if  x == 0  or  x == 1 :     return  1    else :     return  fib(x-1 ) + fib(x-2 ) 
 
Recursion On Non-numerics 如何判断回文
Solving Recursively? 
只留下字母并统一转化为小写 
Base case:长度为0或者1的字符串是回文 Recursive case:如果第一个字母和最后一个字母相同,中间部分是回文,那么他就是回文 
 
Example 省略 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def  isPalindrome (s) :  def  toChars (s) :     s = s.lower()     ans = ''      for  c in  s:       if  c in  'abcdefghijklmnopqrstuvwxyz' :         ans = ans + c     return  ans   def  isPal (s) :     if  len(s) <= 1 :       return  True      else :       return  s[0 ] == s[-1 ] and  isPal(s[1 :-1 ])   return  isPal(toChars(s)) 
 
How To Store Student Info(这里开始讲字典) 
1 2 3 names = ['Ana' , 'John' , 'Denise' , 'Katy' ] grade = ['B' , 'A+' , 'A' , 'A' ] course = ['2.00' , '6.0001' , '20.002' , '9.01' ] 
 
每一个项目用单独的数组 
每一个数组都必须有一样的长度 
相同数组下标的信息对应,每一个下标指向不同的人 
 
How To Update/Retrieve Student Info 1 2 3 4 5 def  get_grade (student, name_list, grade_list, course_list) :  i = name_list.index(student)   grade = grade_list[i]   course = course_list[i]   return  (course, grade) 
 
如果有很多不同的信息需要追踪的话就很混乱 
必须保持很多数列,并且把它们作为参数传入 
通常使用整数作为下标 
必须记住name_list的下标 
 
A Better And Cleaner Way - A Dictionary 
用直接关心的东西作为下标(并不总是整数) 
使用一个数据结构,而不是单独的数组 
 
A dictionary 
Key 
Value 
 
 
 Key 1 
Val 1 
 
 Key 2 
Val 2 
 
 Key 3 
Val 3 
 
 Key 4 
Val 4 
 
 … 
…  
 
 
A Python Dictionary 
1 2 my_dect = {} grade = {'Ana' : 'B' , 'John' : 'A+' , 'Denise' : 'A' , 'Katy' : 'A' } 
 
Dictionary Lookup 
和数组的下标很像 
使用key来查找 
返回和key相关联的值 
如果key没有找到,返回error 
 
 
Dictionary Operations 1 2 3 4 5 6 7 8 9 10 11 12 13 14 grades['Sylvan' ] = 'A'  'John'  in  gradesdel (grades['Awa' ])grades.keys() grades.values() 
 
键要求唯一性,并且不可变性:整数,浮点数,字符串,元祖,布尔值
list vs dict 
list 
dict 
 
 
 元素的有序集合 
键值匹配 
 
 通过整数型下标来查找元素 
通过一个item来查找另一个item 
 
 有序目录 
不保证顺序 
 
 下标是一个整数 
键可以是任何一个不可变类型 
 
 
Creating A Dictionary  一个记录歌词频率的例子 
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 def  lyrics_to_frequencies (lyrics) :  myDict = {}   for  word in  lyrics:     if  word in  myDict:       myDict[word] += 1      else :       myDict[word] = 1    return  myDict def  mosy_common_word (freqs) :  value = freqs.values()   best = max(values)   word = []   for  k in  freqs:     if  freqs[k] == best:       word.append(k)   return (words, best) def  word_often (freqs, minTimes) :  result = []   done = False    while  not  done:     temp = most_common_words(freqs)     if  temp[1 ] >= minTimes:       result.append(temp)       for  w in  temp[0 ]:         del (freqs[w])     else :       done = True    return  result print(word_often()) 
 
Inefficient Fibonacci fib(n) = fib(n-1) + fib(n-2)
1 2 3 4 5 6 7                 fib(5)                   ↙↘           fib(4)        fib(3)           ↙↘              ↙↘     fib(3) fib(2)    fib(2) fib(1)     ↙↘ fib(2) fib(1) 
 
可以看到同一个值重复计算了多遍
Fibonacci With A Dictionary 1 2 3 4 5 6 7 8 9 def  fib_efficient (n, d) :  if  n in  d:     return  d[n]   else :      ans = fib_efficient(n-1 , d) + fib_efficient(n-2 , d)     d[n] = ans     return  ans d = {1 :1 , 2 :2 } print(fib_efficient(6 , d)) 
 
Testing, Debugging, Exceptions, and Assertions We Aim For High Quality —— An Analogy With Soup 一个编程debug的类比举例 
Programing So Far… 会遇到运行的代码和期望的代码不一致的情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14                               测试/验证                               * 对照规格,比照输入输出                               * "It's not working!"                               * "How can I break my program?"                   ---> 防御性编程 * 编写函数规格 * 程序模块化 * 检查输入输出(断言)的条件                   --->                               调试                               * 研究引起错误的事件                               * "Why is it not working?"                               * "How can I fix my program?" 
 
Classes of Tests 
单元测试
 
回归测试
对于找到的bug添加测试 
修复的之前的error不会再次引入别的error 
 
 
集成测试
 
 
(这是一个测试循环)
Testing Approaches 
关于问题的自然边界的直觉(比如相等时,最大最小)
 
黑盒测试——根据规格文档上的测试用例 
白盒测试——根据代码的路径写测试用例测试(测试集包含每一段代码路径)
分支的话,包含所有的条件 
for循环的话,没进入循环,循环一次,循环不止一次 
while循环的话,和for循环一样,还包含所有退出while循环的可能方法 
 
 
 
Print 你随时可以使用Print来debug你的代码。你可以在函数和循环中使用print来确保是否是正确的传递和正确的值在传递。你也可以使用二分法,直到精确定位。
Debugging Steps 
Error Message - Easy 一些报错信息分析 
Logic Errors - Hard 
先思考再写新的代码 
画图,休息 
橡皮鸭调试发(或者向某人解释代码) 
 
Dos & Donts Of Debugging And Testing 
Don’t 
Do 
 
 
 写整个程序 
写一个函数 
 
 测试整个程序 
测试并调试函数 
 
 调试整个程序 
重复以上过程 
 
 
单元测试 -> 回归测试 -> 集成测试 
 
 
Don’t 
Do 
 
 
 更改代码 
备份代码 
 
 记住什么bug 
更改代码 
 
 测试代码 
用注释写下潜在的bug 
 
 忘记改哪里了 
测试代码 
 
 疯了 
新旧对比 
 
 
Other Types Of Exceptions 
Dealing With Exceptions 
1 2 3 4 5 try :  a = int(input("Tell me one number:" ))   b = int(input("Tell me another number:" )) except :   print("Bug in user input." ) 
 
把你认为可能有异常错误的部分放入try,如果发生异常,有except语句的话,就会执行except中的内容。
Handling Specific Exceptions 
1 2 3 4 5 6 7 8 9 10 try :  a = int(input("Tell me one number:" ))   b = int(input("Tell me another number:" ))   print("a/b = " , a/b) except  ValueError:   print("Could not convert to a number." ) except  ZeroDivisionError:   print("Can't divide by zero." ) except :   print("Something won't very wrong." ) 
 
运行类似于if,elseif,else 
Other Exceptions 
try部分没有异常的完成时执行
在try,else,except之后执行,即使引发另一个错误或者执行过break,continue,return。适合用于无论发生什么都要使用的清理代码
What To Do With Exceptions? 
发现错误的时候做什么?
 
默默失败
用默认值替代或者仅仅继续运行 
坏主意,用户并没有得到warning 
 
 
返回一个“error”值
 
停止
in Python: 提出异常raise Exception("descriptive string") 
 
 
 
Exceptions As Control Flow 
错误发生的时候不要返回特殊值,检查是否‘错误值’已经被返回 
事实上,当不能产生和函数规格一致的结果时,提出异常(这种情况下并不会返回错误值,而你可以自己提出异常) 
 
raise <exceptionName>(<arguments>)
Example:Raising An Exception 
Example Of Exception 
Assertion Example 1 2 3 def  avg (grades) :  assert  not  len(grades) == 0 , 'no grades data'    return  sum(grades)/len(grades) 
 
如果给了grades一个空列表,那么会引起AssertionError 
其他的运行ok 
一旦引起了断言错误,那么函数将立即终止(只要先决条件不成立,会阻止程序) 
 
Where To Use Assertions? 
想要一旦发生bug就停止,清楚知道在哪发生的情况 
作为测试的增补 
如果用户提供坏的数据输入就引起异常 
使用断言是为了:
检查参数和值的类型 
检查数据结构的变量 
检查返回值的约束条件 … 
 
 
 
Black Box and Glass Box Testing 
Errors 
Exceptions 
              
            
             
            
            
  
 为正常使用来必力评论功能请激活JavaScript