Day7 - 面向对象编程进阶及其他相关
?
參考文章:http://www.cnblogs.com/alex3714/articles/5213184.html
本節內容:
- 面向對象高級語法部分
- 靜態方法、類方法、屬性方法
- 類的特殊成員方法
- 反射
- 異常處理
- Socket開發基礎
?
?
?
靜態方法 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
通過?@staticmethod 裝飾器即可把其裝飾的方法變為一個靜態方法,什么是靜態方法呢?其實不難理解,普通的方法,可以在實例化后直接調用,并且在方法里可以通過self.調用實例變量或類變量,但靜態方法是不可以訪問實例變量或類變量的(只是名義上歸類管理),一個不能訪問實例變量和類變量的方法,其實跟類本身已經沒什么關系了,它與類唯一的關聯就是需要通過類名來調用這個方法。
1 class Dog(object): 2 def __init__(self, name): 3 self.name = name 4 5 @staticmethod # 把eat方法變為靜態方法 6 def eat(self): 7 print("%s is eating" % self.name) 8 9 d = Dog("abc") 10 d.eat()上面的調用會出以下錯誤,說是 eat 需要一個 sel f參數,但調用時卻沒有傳遞,沒錯,當 eat 變成靜態方法后,再通過實例調用時就不會自動把實例本身當作一個參數傳給 self 了。
1 Traceback (most recent call last): 2 File "D:/python_code/day6/001.py", line 10, in <module> 3 d.eat() 4 TypeError: eat() missing 1 required positional argument: 'self'想讓上面的代碼可以正常工作有兩種辦法
1. 調用時主動傳遞實例本身給 eat 方法,即 d.eat(d) ,可以通過 obj.?調用示例中的其它變量。
2. 在eat方法中去掉 sel f參數,但這也意味著,在 eat 中不能通過 self.?調用實例中的其它變量了
1 class Dog(object): 2 3 def __init__(self,name): 4 self.name = name 5 6 @staticmethod 7 def eat(): 8 print(" is eating") 9 10 d = Dog("abc") 11 d.eat()?
?
類方法 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
類方法通過 @classmethod 裝飾器實現,類方法和普通方法的區別是, 類方法只能訪問類變量(公有屬性),不能訪問實例變量
1 class Dog(object): 2 def __init__(self, name): 3 self.name = name 4 5 @classmethod 6 def eat(self): 7 print("%s is eating" % self.name) 8 9 d = Dog("abc") 10 d.eat()執行報錯如下,說Dog沒有name屬性,因為name是個實例變量,類方法是不能訪問實例變量的
1 Traceback (most recent call last): 2 File "D:/python_code/day6/001.py", line 10, in <module> 3 d.eat() 4 File "D:/python_code/day6/001.py", line 7, in eat 5 print("%s is eating" % self.name) 6 AttributeError: type object 'Dog' has no attribute 'name'此時可以定義一個類變量(公有屬性),也叫name,看下執行效果
1 class Dog(object): 2 3 name = "我是類變量" 4 5 def __init__(self, name): 6 self.name = name 7 8 @classmethod 9 def eat(self): 10 print("%s is eating" % self.name) 11 12 d = Dog("abc") 13 d.eat() 14 15 執行結果: 16 我是類變量 is eating?
?
屬性方法 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
屬性方法的作用就是通過 @property 裝飾器把一個方法變成一個靜態屬性
1 class Dog(object): 2 3 def __init__(self, name): 4 self.name = name 5 6 @property 7 def eat(self): 8 print("%s is eating" % self.name) 9 10 d = Dog("abc") 11 d.eat()調用會出以下錯誤, 說NoneType is not callable, 因為eat此時已經變成一個靜態屬性了, 不是方法了, 想調用已經不需要加()號了,直接d.eat就可以了
1 ChenRonghua is eating 2 Traceback (most recent call last): 3 File "D:/python_code/day6/001.py", line 11, in <module> 4 d.eat() 5 TypeError: 'NoneType' object is not callable正常調用如下
1 d = Dog("abc") 2 d.eat 3 4 輸出 5 ChenRonghua is eating?
變成靜態屬性后,?想調用已經不需要加()號,也不可以給它傳參數了,還不可以直接通過 del 語法刪除,因為靜態屬性默認無法刪除。傳參數、刪除都必須在類里在重新定義一個同名的方法。
1 class Dog(object): 2 def __init__(self, name): 3 self.name = name 4 self.__food = None 5 6 @property # attribute 7 def eat(self): 8 print("%s is eating %s" % (self.name, self.__food)) 9 @eat.setter 10 def eat(self, food): #修改(賦值) 11 print("set to food:", food) 12 self.__food = food 13 @eat.deleter 14 def eat(self): #刪除 15 del self.__food 16 print("刪完了") 17 18 d = Dog("abc") 19 d.eat 20 d.eat = "包子" #觸發@eat.setter 21 d.eat 22 del d.eat #觸發@eat.daleter執行結果:
1 abc is eating None 2 set to food: 包子 3 abc is eating 包子 4 刪完了?
屬性方法的應用實例:
好吧,把一個方法變成靜態屬性有什么卵用呢?既然想要靜態變量,那直接定義成一個靜態變量不就得了么?well, 以后你會需到很多場景是不能簡單通過 定義 靜態屬性來實現的, 比如 ,你想知道一個航班當前的狀態,是到達了、延遲了、取消了、還是已經飛走了, 想知道這種狀態你必須經歷以下幾步:
1. 連接航空公司API查詢
2. 對查詢結果進行解析?
3. 返回結果給你的用戶
因此這個status屬性的值是一系列動作后才得到的結果,所以你每次調用時,其實它都要經過一系列的動作才返回你結果,但這些動作過程不需要用戶關心, 用戶只需要調用這個屬性就可以,明白 了么?
1 class Flight(object): 2 def __init__(self, name): 3 self.flight_name = name 4 5 def checking_status(self): 6 print("checking flight %s status " % self.flight_name) 7 return 1 8 9 @property 10 def flight_status(self): 11 status = self.checking_status() 12 if status == 0: 13 print("flight got canceled...") 14 elif status == 1: 15 print("flight is arrived...") 16 elif status == 2: 17 print("flight has departured already...") 18 else: 19 print("cannot confirm the flight status...,please check later") 20 21 @flight_status.setter # 修改 22 def flight_status(self, status): 23 status_dic = { 24 0: "canceled", 25 1: "arrived", 26 2: "departured" 27 } 28 print("\033[31;1mHas changed the flight status to \033[0m", status_dic.get(status)) 29 30 @flight_status.deleter # 刪除 31 def flight_status(self): 32 print("status got removed...") 33 34 35 f = Flight("CA980") 36 f.flight_status 37 f.flight_status = 2 # 觸發@flight_status.setter 38 del f.flight_status # 觸發@flight_status.deleter flight_status?
?
類的特殊成員方法 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
1. __doc__ 表示類的描述信息
1 class Dog(object): 2 '''這個類是描述狗這個對象的''' 3 4 def func(self): 5 pass 6 7 print(Dog.__doc__) 8 9 #輸出:這個類是描述狗這個對象的 __doc__2.?__module__ 和 ?__class__?
__module__ 表示當前操作的對象在那個模塊
__class__ ? ? 表示當前操作的對象的類是什么
1 class C: 2 3 def __init__(self): 4 self.name = 'abc' lib/aa.py 1 from lib.aa import C 2 3 obj = C() 4 print obj.__module__ # 輸出 lib.aa,即:輸出模塊 5 print obj.__class__ # 輸出<class ' lib.aa.C'>,即:輸出類 index.py3. __init__ 構造方法,通過類創建對象時,自動觸發執行。
4.__del__
析構方法,當對象在內存中被釋放時,自動觸發執行。通常用于做一些收尾工作,如關閉一些數據庫連接,關閉打開的臨時文件。
注:此方法一般無須定義,因為Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的
?5. __call__?對象后面加括號,觸發執行。
注:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對于 __call__ 方法的執行是由對象后加括號觸發的,即:對象() 或者 類()()
1 class Foo(object): 2 def __init__(self,name): 3 self.name =name 4 print('__init__') 5 6 def __call__(self, *args, **kwargs): 7 print('__call__') 8 9 10 obj = Foo('abc') # 執行 __init__ 11 #輸出:__init__ 12 obj() # 執行 __call__ 13 #輸出:__call__ 14 Foo('abc')() # 執行 __call__ 15 #輸出:__init__、__call__ __call__6. __dict__ 查看類或對象中的所有成員?
1 class Province(object): 2 country = 'China' 3 4 def __init__(self, name, count): 5 self.name = name 6 self.count = count 7 8 def func(self, *args, **kwargs): 9 print('func') 10 11 # 獲取類的所有屬性,不包括實例屬性,即:公有屬性(靜態字段)、方法 12 print(Province.__dict__) 13 # 輸出:{'func': <function Province.func at 0x000001A21E77EC80>, '__dict__': <attribute '__dict__' of 'Province' objects>, 'country': 'China', '__weakref__': <attribute '__weakref__' of 'Province' objects>, '__init__': <function Province.__init__ at 0x000001A21E77EBF8>, '__doc__': None, '__module__': '__main__'} 14 15 obj1 = Province('HeBei', 10000) 16 obj1.func() 17 # 獲取實例 obj1 的所有屬性,不包括類屬性 18 print(obj1.__dict__) 19 # 輸出:{'count': 10000, 'name': 'HeBei'} 20 21 obj2 = Province('HeNan', 3888) 22 obj2.func() 23 print(obj2.__dict__) 24 # 獲取 對象 obj2 的成員 25 # 輸出:{'count': 3888, 'name': 'HeNan'} __dict__7.__str__?如果一個類中定義了__str__方法,那么在打印 對象 時,默認輸出該方法的返回值。
1 class Foo(object): 2 def __str__(self): 3 return "__str__" 4 5 obj = Foo() 6 print(obj) 7 # 輸出:__str__ __str__8.__getitem__、__setitem__、__delitem__
用于索引操作,如字典。以上分別表示獲取、設置、刪除數據
1 __author__ = "Alex Li" 2 3 4 class Foo(object): 5 def __init__(self): 6 self.data = {} 7 def __getitem__(self, key): #獲取 8 print('__getitem__', key) 9 return self.data.get(key) 10 def __setitem__(self, key, value): #設置 11 print('__setitem__', key, value) 12 self.data[key] =value 13 def __delitem__(self, key): #刪除 14 print('__delitem__', key) 15 16 obj = Foo() 17 obj['name'] = "abc" # 自動觸發執行 __setitem__ 18 print(obj['name']) #輸出:abc 19 print(obj.data) #輸出:{'name': 'abc'} 20 del obj["sdfdsf"] # 自動觸發執行 __delitem__,刪沒刪除看 __delitem__ 方法里有沒有刪除 21 result = obj['name'] # 自動觸發執行 __getitem__ 22 print(result) #輸出:abc 23 obj['k2'] = 'abc' # 自動觸發執行 __setitem__ 24 del obj['k1'] 25 print(obj['name']) #輸出:abc 26 print(obj.data) #輸出:{'name': 'abc', 'k2': 'abc'} __getitem__、__setitem__、__delitem__9. __new__ \ __metaclass__
1 class Foo(object): 2 def __init__(self, name): 3 self.name = name 4 5 f = Foo("abc") Foo上述代碼中,f 是通過 Foo 類實例化的對象,其實,不僅 obj 是一個對象,Foo類本身也是一個對象,因為在Python中一切事物都是對象。
如果按照一切事物都是對象的理論:obj對象是通過執行Foo類的構造方法創建,那么Foo類對象應該也是通過執行某個類的 構造方法 創建。
1 print(type(f)) # 輸出:<class '__main__.Foo'> 表示:f 對象由Foo類創建 2 print(type(Foo)) # 輸出:<type 'type'> 表示,Foo類對象由 type 類創建所以,f對象是Foo類的一個實例,Foo類對象是 type 類的一個實例,即:Foo類對象 是通過type類的構造方法創建。
那么,創建類就可以有兩種方式:
a). 普通方式?
1 class Foo(object): 2 3 def func(self): 4 print ('hello world!')b). 特殊方式
1 def func(self): 2 print('hello world!') 3 4 # type --> 類的類 5 Foo = type('Foo', (object,), {'func': func}) #新式類 6 #Foo = type('Foo', (), {'func': func}) #經典類 7 # type第一個參數:類名 8 # type第二個參數:當前類的基類; 新式類:(object,) 、經典類:() 9 # type第三個參數:類的成員 1 def func(self): 2 print('hello %s' %self.name) 3 4 def __init__(self,name,age): 5 self.name = name 6 self.age = age 7 # type --> 類的類 8 Foo = type('Foo', (object,), {'talk': func, 9 '__init__':__init__}) 10 f = Foo("world",22) 11 f.talk() #輸出:hello world 12 print(type(f)) #輸出:<class '__main__.Foo'> 13 print(type(Foo)) #輸出:<class 'type'> 加上構造方法所以說,類 是由 type 類實例化產生
那么問題來了,類默認是由 type 類實例化產生,type類中如何實現的創建類?類又是如何創建對象?
答:類中有一個屬性?__metaclass__,其用來表示該類由 誰 來實例化創建,所以,我們可以為?__metaclass__ 設置一個type類的派生類,從而查看 類 創建的過程。
1 class MyType(type): 2 def __init__(self, what, bases=None, dict=None): 3 print("MyType __init__") 4 super(MyType, self).__init__(what, bases, dict) 5 6 def __call__(self, *args, **kwargs): 7 print("MyType __call__") 8 obj = self.__new__(self, *args, **kwargs) 9 #obj.data = {"name":111} 10 self.__init__(obj, *args, **kwargs) 11 12 class Foo(object): 13 __metaclass__ = MyType #元類:__metaclass__,跟 MyType 關聯 14 15 def __init__(self, name): 16 self.name = name 17 print("Foo __init__") 18 19 def __new__(cls, *args, **kwargs): #用來創建實例的 20 print("Foo __new__") 21 #print(object.__new__(cls)) 22 return object.__new__(cls) #繼承父類的__new__方法,一定要用 return 23 24 # 第一階段:解釋器從上到下執行代碼創建Foo類 25 # 第二階段:通過Foo類創建obj對象 26 # 類的生成調用順序依次是 __new__ --> __init__ --> __call__ 27 obj = Foo("Alex") 28 print(obj.name) 自定義元類?類的生成 調用 順序依次是 __new__ --> __init__ --> __call__
__new__ : 用來創建實例的,一般無須定義,自動存在,定義就是重構__new__方法
?
?
反射? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
反射是通過字符串的形式操作對象相關的成員。一切事物都是對象!!!
把字符串反射(映射)成對象的方法或屬性的內存地址。(動態的內存裝配)
python中的反射功能是由以下四個內置函數提供:hasattr、getattr、setattr、delattr,這四個函數分別用于對對象內部執行:檢查是否含有某成員、獲取成員、設置成員、刪除成員
?
?
異常處理 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
1、異常基礎
在編程過程中為了增加友好性,在程序出現bug時一般不會將錯誤信息顯示給用戶,而是現實一個提示的頁面,通俗來說就是不讓用戶看見大黃頁!!!
1 try: 2 pass 3 except Exception as e: 4 print(e)需求:將用戶輸入的兩個數字相加
while True:num1 = raw_input('num1:')num2 = raw_input('num2:')try:num1 = int(num1)num2 = int(num2)result = num1 + num2except Exception, e:print '出現異常,信息如下:'print e2、異常種類
python中的異常種類非常多,每個異常專門用于處理某一項異常!!!
1 AttributeError 試圖訪問一個對象沒有的樹形,比如foo.x,但是foo沒有屬性x 2 IOError 輸入/輸出異常;基本上是無法打開文件 3 ImportError 無法引入模塊或包;基本上是路徑問題或名稱錯誤 4 IndentationError 語法錯誤(的子類) ;代碼沒有正確對齊 5 IndexError 下標索引超出序列邊界,比如當x只有三個元素,卻試圖訪問x[5] 6 KeyError 試圖訪問字典里不存在的鍵 7 KeyboardInterrupt Ctrl+C被按下 8 NameError 使用一個還未被賦予對象的變量 9 SyntaxError Python代碼非法,代碼不能編譯 10 TypeError 傳入對象類型與要求的不符合 11 UnboundLocalError 試圖訪問一個還未被設置的局部變量,基本上是由于另有一個同名的全局變量,導致你以為正在訪問它 12 ValueError 傳入一個調用者不期望的值,即使值的類型是正確的 常用異常 1 ArithmeticError 2 AssertionError 3 AttributeError 4 BaseException 5 BufferError 6 BytesWarning 7 DeprecationWarning 8 EnvironmentError 9 EOFError 10 Exception 11 FloatingPointError 12 FutureWarning 13 GeneratorExit 14 ImportError 15 ImportWarning 16 IndentationError 17 IndexError 18 IOError 19 KeyboardInterrupt 20 KeyError 21 LookupError 22 MemoryError 23 NameError 24 NotImplementedError 25 OSError 26 OverflowError 27 PendingDeprecationWarning 28 ReferenceError 29 RuntimeError 30 RuntimeWarning 31 StandardError 32 StopIteration 33 SyntaxError 34 SyntaxWarning 35 SystemError 36 SystemExit 37 TabError 38 TypeError 39 UnboundLocalError 40 UnicodeDecodeError 41 UnicodeEncodeError 42 UnicodeError 43 UnicodeTranslateError 44 UnicodeWarning 45 UserWarning 46 ValueError 47 Warning 48 ZeroDivisionError 更多異常 1 dic = ["a", "b","c"] 2 try: 3 print(dic[10]) 4 except IndexError as e: 5 print("錯誤:",e) 實例:IndexError 1 dic = {'k1':'v1'} 2 try: 3 dic['k20'] 4 except KeyError as e: 5 print(e) 實例:KeyError 1 s1 = 'hello' 2 try: 3 int(s1) 4 except ValueError as e: 5 print(e) 實例:ValueError對于上述實例,異常類只能用來處理指定的異常情況,如果非指定異常則無法處理。
1 # 未捕獲到異常,程序直接報錯 2 3 s1 = 'hello' 4 try: 5 int(s1) 6 except IndexError as e: 7 print(e)所以,寫程序時需要考慮到try代碼塊中可能出現的任意異常,可以這樣寫:
1 s1 = 'hello' 2 try: 3 int(s1) 4 except IndexError as e: 5 print(e) 6 except KeyError as e: 7 print(e) 8 except ValueError as e: 9 print(e)萬能異常 在python的異常中,有一個萬能異常:Exception,他可以捕獲任意異常,即:
s1 = 'hello' try:int(s1) except Exception as e:print(e)接下來你可能要問了,既然有這個萬能異常,其他異常是不是就可以忽略了!
答:當然不是,對于特殊處理或提醒的異常需要先定義,最后定義Exception來確保程序正常運行。
1 s1 = 'hello' 2 try: 3 int(s1) 4 except KeyError ase: 5 print ('鍵錯誤') 6 except IndexError as e: 7 print( '索引錯誤') 8 except Exception as e: 9 print ('錯誤')3、異常其他結構
1 try: 2 # 主代碼塊 3 pass 4 except KeyError as e: 5 # 異常時,執行該塊 6 pass 7 else: 8 # 主代碼塊執行完,執行該塊 9 pass 10 finally: 11 # 無論異常與否,最終執行該塊 12 pass4、主動觸發異常
try:raise Exception('錯誤了。。。') except Exception as e:print(e)5、自定義異常
1 class MyException(Exception): 2 def __init__(self, msg): 3 self.message = msg 4 5 #def __str__(self): 6 #return self.message 7 8 try: 9 raise MyException('我的自定義異常') 10 except MyException as e: 11 print(e)6、斷言
轉載于:https://www.cnblogs.com/zjtong/p/7376617.html
總結
以上是生活随笔為你收集整理的Day7 - 面向对象编程进阶及其他相关的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UWP入门(八)--几个简单的控件
- 下一篇: Ubuntu - 安装 jdk 、配置