python學習筆記-(十一)面向對象進階&異常處理


上篇我們已經了解了一些面向對象的基礎知識,本次就了解下面向對象的一些進階知識(雖然我也不知道有什么卵用)。

 

靜態方法

靜態方法是一種普通函數,就位於類定義的命名空間中,它不會對任何實例類型進行操作。使用裝飾器@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) 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM