1. 程式人生 > 實用技巧 >SICP 課程總結 & 複習

SICP 課程總結 & 複習

SICP 課程總結 & 複習

小作文

有賴於那個終極的、偉大的、命定的教務系統,我選上了這門課:SICP,Structure and Interpret of Computer Programs,計算機程式的構造與解釋。

 

作為一門程式設計課,SICP頗有一種包羅永珍的氣質:講授三種程式語言;涉及一眾程式設計正規化;更由於馮新宇、李樾兩位老師都是程式設計語言(Programming Languages)界的大牛,這門課同樣包含了許多考試範圍外的 PL 概念。如果你常常在課程群裡提問,甚至還能瞭解到如何證明TSP可以在多項式時間內驗證之類的問題。總之是洋洋大觀。

由於上課的時候說到許多概念都是英文,所以具體內容我也用英文寫一下吧(

The curriculum SICP concentrates on the idea of abstraction, using Python, Scheme and SQL three languages to reveal various programming paradigm including imperative, declarative, functional, object-oriented and generic programming, and to cover numerous advanced concepts like higher-order function, closure, macro, polymorphism, metaclass and so on.

 

 

一般的評論都認為南大的SICP是一門實驗性、革新性的課程。

先說實驗性:

首先,今年也就剛剛是SICP第二年開課。按馮新宇老師的比喻,我們也就算是黃埔二期生,很有實驗性。

其次,計算機系的後續課程都是基於C/C++的,而SICP很有實驗性色彩地,全然不涉及C/C++內容。因此,雖然SICP和程式設計基礎(講授C/C++的傳統課程)是二選一的平行課,基本沒有學生會單選SICP,應該也只有我這樣的轉專業抽籤倒黴蛋例外了。

如果還要再說一點的話,SICP破天荒地用了五位助教。五位助教老師一方面高山仰止、盡職盡責,一方面和大家打成一片,騷話連篇。幾位助教在群裡耐心解答各類問題,還會額外地講一些型別系統、複雜度分析的知識,進一步擴充了SICP的課程內容,總之就是非常地好。

然後是革新性:

革新性其一就在之前說到的課程內容。據說SICP涉及的一些概念,比如閉包(closure),在南大甚至國內高校的其他所有課程中都是不會講到的。而且就程式設計教育而言,面向無基礎初學者的SICP,竟然涉及瞭如此多難懂甚至晦澀的概念,縱然是蜻蜓點水、淺嘗輒止式地涉及,對初學者來說無疑是一種挑戰。

革新性其二,在於我們這門課的兩位老師:馮新宇、李樾。兩位在 PL 屆都是赫赫有名的大佬。據說國內計算機繫有 PL 方向的高校都是鳳毛麟角,按樾哥的說法,讓他倆來講課也多少有宣傳PL方向的意思。

 

 

 

 

期中以前的內容

寒假想起來再寫吧,期末不考啊(

 

 

 

 

期中以後的內容

Lecture-15: Python Inheritance

Attributes: Look up & Assignment

簡單說來,Attribute 有兩個型別:class attribute & instance attribute。

做 Attribute Look up 時,會優先找 instance attribute,找不到時再找 class attribute,如果還是沒有找到,就繼續上訴到父類,直到找到為止。如果最終還是找不到,就返回一個 attribute error 。

做 Attribute Assignment 時,考慮 dot expression 的兩個部分:

<expression>.<name>

如果 <expression> 是一個 instance,那麼就建立或修改對應的 instance attribute

如果 <expression> 是一個 class,那麼就建立或修改對應的 class attribute

 

當然,class attribute 和 instance attribute 是有可能重名的,於是情況就會變得稍迷惑一些。

考點都在這個例子裡,大概:

class Account:
    interest = 0.02
    def __init__(self, name_str):
        self.name = name_str

jim_account = Account('Jim')
tom_account = Account('Tom')

###################################

>>> tom_account.interest
0.02
>>> jim_account.interest
0.02
>>> Account.interest = 0.04
>>> tom_account.interest
0.04
>>> jim_account.interest
0.04
>>> jim_account.interest = 0.08
>>> tom_account.interest
0.04
>>> jim_account.interest
0.08
>>> Account.interest = 0.05
>>> tom_account.interest
0.05
>>> jim_account.interest
0.08

 

Inheritance, Multiple Inheritance

Inheritance 寫法上很簡單:

class <Name>(<Base Class>):
    <suite>

子類會顧名思義地繼承父類的 class attributes,包括所有的 methods。

可以在 <suite> 部分任意的覆寫父類的內容,也當然可以加入新的。沒有覆寫的attributes一律預設使用父類的。

 

Multiple Inheritance 同樣很容易寫:

class <Name>(<Base1>, <Base2>, ...):
    <suite>

當然,這裡不可避免地會涉及 Diamond Problem。Python的處理辦法是Method Resolution Order,說實話我覺得相當迷惑。還是 C++ 寫起來安心(

樾哥提到 Python 並不適合大規模的開發使用,寫一點精短的小程式的話,這樣的設計應該也還受用吧。

這個應該不是重點。

 

Quiz

難倒是不難,但是這是人寫的程式碼嗎……

class A:
    z = -1
    def f(self, x):
        return B(x - 1)
    
class B(A):
    n = 4
    def __init__(self, y):
        if y:
            self.z = self.f(y)
        else:
            self.z = C(y + 1)
            
class C(B):
    def f(self, x):
        return x

Quesion:

  1.  >>> C(2).n
     ???
    
  2.  >>> a.z == C.z
     ???
    
  3.  >>> a.z == b.z
     ???
    
  4. Which evaluates to an integer?

    b.z
    b.z.z
    b.z.z.z
    b.z.z.z.z
    

 

答案是 4, True, False, b.z.z.z

 

Extensions:

  1. The definition of expressions

    https://docs.python.org/3/reference/expressions.html

  2. Metaclass, duck type and other things about type system

    Python中的 type 就是一個 metaclass ,也就是可以建立其它 class 的,一種更加形而上的 class。

    >>>type(jim_account)
    <class 'Account'>
    >>>type(Account)
    <class 'type'>
    

    而如果你試圖用 Python 研究型別系統,得到

    >>>type(type)
    <class 'type'>
    

    也不必驚訝,這是 duck type 的緣故,參見

    https://en.wikipedia.org/wiki/Duck_typing

  3. Inheritance, composition and mixin

    Inheritance 是個很恐怖的東西。課件裡寫到,Inheritance helps code reuse but NOT for code reuse。繼承的有兩個主要的壞處,一是破壞封裝,你不得不上溯父類;二是可能會繼承冗餘的資訊。我印象中網上關於繼承和耦合性還有很多有意思的釣魚文。

    實際上在做和 class 有關 code reuse 的時候,inheritance, composition 和 mixin 都是可能的選項。

    可以參見

    https://naildrivin5.com/blog/2012/12/19/re-use-in-oo-inheritance.html

    說實話mixin的理解還是有點難度的。

  4. Diamond Problem

    http://www.srikanthtechnologies.com/blog/python/mro.aspx

 

 

Lecture-16: Special Methods

Special Methods

簡單地說就是兩個函式 str()repr() ,傳進某個 instance 就會給出一個顯式的字串表達。

其中 str() 的返回結果更加 human readable,而 repr() 很大程度上是給直譯器看的。

譬如說

>>> from fractions import Fraction
>>> half = Fraction(1, 2)
>>> repr(half)
'Fraction(1, 2)'
>>> str(half)
'1/2'

特別地,如果沒有實現 str() 的話呼叫會預設返回 repr() 的結果。

這兩個函式就有多型( Polymorphism )的性質。

 

實現上很簡單:

class Ratio:
    def __init__(self, numerator, denominator):
    	self.n = numerator
        self.d = denominator
    def __repr__(self):
        return "Ratio({0}, {1})".format(self.n, self.d)
    def __str__(self):
        return "{0}/{1}".format(self.n, self.d)

 

實現過載操作符也是類似可行的:

class Ratio:
    def __init__(self, numer, denom):
        from math import gcd
        self.n, self.d = numer // gcd(numer, denom), \
                         denom // gcd(numer, denom)
    def __repr__(self):
        return "Ratio({0}, {1})".format(self.n, self.d)
    def __str__(self):
        return "{0}/{1}".format(self.n, self.d)   
    def __add__(self, other):
        self = Ratio(self.n * other.d + self.d * other.n,\
                     self.d * other.d                    )

 

過載操作符的時候常常會遇到 <class A> + <class B> 能用,<class B> + <class A> 就不行了的情況。這時候只需要新增一行 __radd__ = __add__ 就可以了。

 

Extensions

  1. Polymorphism

    分成三類 Ad Hoc Polymorphism, Parametric Polymorphism & Inclusion Polymorphism。課間上破天荒給了C++程式碼示例:

    // Ad Hoc Polymorphism
    foo(int) {}
    foo(string) {}
    
    // Parametic Polymorphism
    Template<typename T>
    T foo(T x, T y) {
        return (x > y)? x: y;
    }
    foo<int>(3, 7)
    foo<char>('h', 'k')
        
    // Inclusion Polymorphism
    T v;	// T has many types
    v.foo();
    

    在這恐怖的課堂看見C++,就像回家了一樣(

    參見

    https://en.wikipedia.org/wiki/Polymorphism_(computer_science)

 

Lecture-17: Linked Lists & Trees

就是實現兩個類:連結串列和樹

感覺沒啥可寫的,這節課說實話沒啥資訊量,放在這裡應該是做一個 class 和 OOP 的總結,然後引入連結串列給 Scheme 開個頭吧。

Lecture-18: Scheme