上篇我們已經了解了一些面向對象的基礎知識,本次就了解下面向對象的一些進階知識(雖然我也不知道有什么卵用)。
靜態方法
靜態方法是一種普通函數,就位於類定義的命名空間中,它不會對任何實例類型進行操作。使用裝飾器@staticmethod定義靜態方法。類對象和實例都可以調用靜態方法;
說了那么多,估計會有些懵逼,咱們還是直接上代碼看下靜態方法怎么使用吧!
1.按照正常邏輯編寫代碼並加上@staticmethod定義靜態方法eat:
class People(object): def __init__(self,name): self.name = name @staticmethod #把eat方法變為靜態方法 def eat(self): print("%s is eating" % self.name) d = People("cc") d.eat()
運行上面代碼,我們會發現報以下錯誤:
TypeError: eat() missing 1 required positional argument: 'self'
----------eat需要一個self參數,但調用時卻沒有傳遞
so...我們可以得出一個結論:eat變成靜態方法后,再通過實例調用時不會自動把實例本身當作一個參數傳給self
2.解決辦法:
1)調用時主動傳遞實例本身給eat方法,即d.eat(d)
class People(object): def __init__(self, name): self.name = name @staticmethod # 把eat方法變為靜態方法 def eat(self): print("%s is eating" % self.name) d = People("cc") d.eat(d) #------打印輸出------ #cc is eating
2)在eat方法中去掉self參數(這也意味着,在eat中不能通過self.調用實例中的其它變量了)
class People(object): def __init__(self, name): self.name = name @staticmethod # 把eat方法變為靜態方法 def eat(): print("%s is eating" % self.name) d = People("cc") d.eat() #------------------打印輸出---------------- #print("%s is eating" % self.name) #NameError: name 'self' is not defined
類方法
類方法是將類本身作為對象進行操作的方法。類方法使用@classmethod裝飾器定義,其第一個參數是類,約定寫為cls。類對象和實例都可以調用類方法。
類方法和普通方法的區別是, 類方法只能訪問類變量,不能訪問實例變量。
依然還是原來的代碼,把eat變為類方法看下:
class People(object): def __init__(self, name): self.name = name @classmethod # 把eat方法變為類方法 def eat(self): print("%s is eating" % self.name) d = People("cc") d.eat() ---------------打印輸出------------------- print("%s is eating" % self.name) AttributeError: type object 'People' has no attribute 'name'
報錯說明:People沒有name屬性;
上面說過,類方法只能訪問類變量,不能訪問實例變量,而name在這里就是實例變量。
我們加上一個類變量試試:
class People(object): name = "類變量" def __init__(self, name): self.name = name @classmethod # 把eat方法變為類方法 def eat(self): print("%s is eating" % self.name) d = People("cc") d.eat() --------------------打印輸出------------------- 類變量 is eating
屬性方法
屬性方法的作用就是通過@property把一個方法變成一個靜態屬性;
依然還是之前的代碼,把eat方法變成靜態屬性看下效果:
class People(object): name = "請叫我類變量" def __init__(self, name): self.name = name @property # 把eat方法變為靜態屬性 def eat(self): print("%s is eating" % self.name) d = People("cc") d.eat() -----------------打印輸出-------------------- d.eat() TypeError: 'NoneType' object is not callable
這里報錯是因為eat已經變成了一個靜態屬性,當然不能再使用()去調用了,我們直接調用試試:
d.eat -------------打印輸出------------ cc is eating
反射
1.反射的定義
根據字符串的形式去某個對象中操作成員
- 根據字符串的形式去一個對象中尋找成員
- 根據字符串的形式去一個對象中設置成員
- 根據字符串的形式去一個對象中刪除成員
- 根據字符串的形式去一個對象中判斷成員是否存在
2. 反射的函數
-
getattr(object, name[, default])
根據字符串的形式去一個對象中尋找成員
class People(object): def __init__(self): self.name = 'cc' def eat(self): return 'HI' d = People() ret1 = getattr(d,'eat') ret2 = getattr(d,'name') r1 = ret1() print(r1) print(ret2) --------------打印輸出---------------- HI cc
-
setattr(object, name, value)
根據字符串的形式去一個對象中設置成員
class People(object): def __init__(self): self.name = 'cc' def eat(self): return 'HI' d = People() set1 = setattr(d,'age',18) r1 = getattr(d,'age') print(r1) -----------------------打印輸出--------------------------- 18
-
delattr(object, name)
根據字符串的形式去一個對象中刪除成員
class People(object): def __init__(self): self.name = 'cc' def eat(self): return 'HI' d = People() del1 = delattr(d,'name') r1 = getattr(d,'name') print(r1) ----------------打印輸出------------------- AttributeError: 'People' object has no attribute 'name'
-
hasattr(object, name)
根據字符串的形式去一個對象中判斷成員是否存在
class People(object): def __init__(self): self.name = 'cc' def eat(self): return 'HI' d = People() h1 = hasattr(d,'age') h2 = hasattr(d,'name') print(h1,h2) ---------------打印輸出----------------- False True
異常處理(缺少else和finally)
在之前學習的過程中我們會接觸到各式各樣的報錯信息,編程過程中為了增加友好性,可以抓取相對應的錯誤並給出提示信息。
常用異常:
AttributeError 試圖訪問一個對象沒有的樹形,比如foo.x,但是foo沒有屬性x IOError 輸入/輸出異常;基本上是無法打開文件 ImportError 無法引入模塊或包;基本上是路徑問題或名稱錯誤 IndentationError 語法錯誤(的子類) ;代碼沒有正確對齊 IndexError 下標索引超出序列邊界,比如當x只有三個元素,卻試圖訪問x[5] KeyError 試圖訪問字典里不存在的鍵 KeyboardInterrupt Ctrl+C被按下 NameError 使用一個還未被賦予對象的變量 SyntaxError Python代碼非法,代碼不能編譯(個人認為這是語法錯誤,寫錯了) TypeError 傳入對象類型與要求的不符合 UnboundLocalError 試圖訪問一個還未被設置的局部變量,基本上是由於另有一個同名的全局變量, 導致你以為正在訪問它 ValueError 傳入一個調用者不期望的值,即使值的類型是正確的
更多異常:
ArithmeticError AssertionError AttributeError BaseException BufferError BytesWarning DeprecationWarning EnvironmentError EOFError Exception FloatingPointError FutureWarning GeneratorExit ImportError ImportWarning IndentationError IndexError IOError KeyboardInterrupt KeyError LookupError MemoryError NameError NotImplementedError OSError OverflowError PendingDeprecationWarning ReferenceError RuntimeError RuntimeWarning StandardError StopIteration SyntaxError SyntaxWarning SystemError SystemExit TabError TypeError UnboundLocalError UnicodeDecodeError UnicodeEncodeError UnicodeError UnicodeTranslateError UnicodeWarning UserWarning ValueError Warning ZeroDivisionError
常用異常實例:
IndexError(輸出指定錯誤信息並打印錯誤信息)
dic = [1,2] try: dic[2] except IndexError as e : print("i got it!\n",e) ---------------------------打印輸出-------------------------- i got it! list index out of range
KeyError(輸出指定錯誤信息並打印錯誤信息)
dic = {'name':'cc'} try: dic['age'] except KeyError as e : print("i got it!\n",e) ---------------------------打印輸出--------------------------- i got it! 'age'
ValueError
s1 = 'hello' try: int(s1) except ValueError as e: print (e) ---------------------------打印輸出---------------------------- invalid literal for int() with base 10: 'hello'
萬能異常Exception:(不建議用,不便於調試;可與異常配合使用)
s1 = 'hello' try: int(s1) except KeyError as e: print('鍵錯誤') except IndexError as e: print('索引錯誤') except Exception as e: print('錯誤')
自定義異常:
class ccException(Exception):
def __init__(self,msg):
self.msg = msg
def __str__(self):
return self.msg
try:
raise ccException("我的異常")
except ccException as e:
print(e)