# 類可以起到模板的作用,因此,可以在創建實例的時候,把一些我們認爲必須綁定的屬性強制填寫進去。 # 通過定義一個特殊的__init__方法,在創建實例的時候,就把屬性綁上去 class Student(object): # 和普通的函數相比,在類中定義的函數只有一點不同,就是第一個參數永遠是實例變量self # Python解釋器自己會把實例變量傳進去 def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 pass def get_attr(self): print(self.attr1) s = Student(111,222) s.get_attr() # 如果要讓內部屬性不被外部訪問,可以把屬性的名稱前加上兩個下劃線__, # 在Python中,實例的變量名如果以__開頭,就變成了一個私有變量(private),只有內部可以訪問,外部不能訪問 class Student(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.__attr2 = attr2 pass s = Student(111,222) print(s.attr1) print(s.__attr2) #繼承和多態 繼承可以把父類的所有功能都直接拿過來,這樣就不必重零做起,子類只需要新增自己特有的方法,也可以把父類不適合的方法覆蓋重寫 class Parent(): def say(self): print('i am parent') # 繼承 class child(Parent): pass c = child() c.say() # 多態 子類覆蓋了父類的同名方法 class child2(Parent): def say(self): print('i am child') c2 = child2() c2.say() # type print(type(123)) print(type(123) == type(456)) # True print(type(123) == int) # True print(type('123')) # <class 'str'> # isinstance()判斷的是一個對象是否是該類型本身,或者位於該類型的父繼承鏈上 class Hello(object): pass print(isinstance(Hello, object)) # True #類似__xxx__的屬性和方法在Python中都是有特殊用途的, # 比如__len__方法返回長度。在Python中,如果你調用len()函數試圖獲取一個對象的長度, # 實際上,在len()函數內部,它自動去調用該對象的__len__()方法 # 下面兩個等價 print(len('123')) print('123'.__len__()) #不要對實例屬性和類屬性使用相同的名字,因爲相同名稱的實例屬性將屏蔽掉類屬性 class Hello(object): name = 'hello' pass h = Hello() print(h.name) # hello h.name = 'world' print(Hello.name) # hello 類屬性 print(h.name) # world 實例屬性,屏蔽了類屬性 del h.name print(h.name) # hello 實例屬性 print(Hello.name) # hello 類屬性 __slots__ 限制給類的實例添加屬性 class Hello(object): __slots__ = ('name') # 實例智能添加name屬性 pass h = Hello() h.name ='leyi' print(h.name) # leyi h.other = '123' # 會報錯 print(h.other) # # @property裝飾器就是負責把一個方法變成屬性調用 class Hello(object): def __init__(self, name): self.name = name; h = Hello('leyi') print(h.name) # 實例可以隨意修改類的屬性,屬性沒經過校驗,這樣被認爲不安全 h.name = 'xxx' print(h.name) # 爲了控制屬性,我們增加方法校驗 class Hello2(object): def __init__(self, num = 0): pass def set_num(self, value): if not isinstance(value, int): raise ValueError('必須爲數字類型') if value < 100 : raise ValueError('必須大於等於100') self.num = value def get_num(self): return self.num pass h2 = Hello2() h2.set_num(121) print(h2.get_num()) # 使用property 裝飾器簡化 class Hello3(object): def __init__(self, n = 0): pass @property # 將下面的方法轉換成屬性 def num(self): return self.n # @property本身又創建了另一個裝飾器@score.setter,負責把一個setter方法變成屬性賦值 @num.setter def num(self,value): if not isinstance(value, int): raise ValueError('必須爲數字類型') if value < 100: raise ValueError('必須大於等於100') self.n = value @property # 不定義setter的話,屬性就是隻讀屬性 def num2(self): return self.n *12 h3 = Hello3() h3.num = 111 # 賦值 print(h3.num) # 取屬性 # h3.num2 = 3333 # 因爲是隻讀屬性,所以賦值會報錯 print(h3.num2) # 取屬性 logging \ assert # 文件讀寫時都有可能產生IOError,一旦出錯, # 後面的f.close()就不會調用。所以,爲了保證無論是否出錯都能正確地關閉文件, # 我們可以使用try ... finally來實現 try : f = open('./b.txt') print(f.read()) finally : if f: f.close() # Python引入了with語句來自動幫我們調用close()方法 with open('./b.txt', 'r') as f1: print(f1.read()) # 如果文件很小,read()一次性讀取最方便;如果不能確定文件大小, # 反覆調用read(size)比較保險;如果是配置文件,調用readlines()最方便 # 反覆調用read def readLines(): pos = 0 while True : with open('./b.txt', 'r') as f2: f2.seek(pos) data = f2.read(4) # 反覆調用readline()也不錯 if data: pos = f2.tell() yield data else: return for i in readLines(): print(i) # 讀取所有行 with open('./b.txt', 'r') as f3: for l in f3.readlines(): print(l)