1. 程式人生 > >python3.x 基礎七:面向對象進階

python3.x 基礎七:面向對象進階

ssm tee ted 接口 onf sin 實例化 基礎 使用

類的高級方法:

1.靜態方法:在類方法前增加關鍵字@staticmethod,將普通方法變成靜態方法,不能再次傳值,不能訪問實例變量或者類變量,與類的關系僅僅是通過類名進行調用

2.類方法:在類方法前增加關鍵字@classmethod,類方法只能訪問類變量,不能訪問實例變量

3.屬性方法:(重點)在類方法前增加關鍵字@property,調用的時候通過屬性一樣的方式訪問(去掉括號調用),可以通過類私有屬性加@setter重新賦值,@deleter刪除私有屬性後方能刪除屬性方法

  • 靜態方法:
class Dog(object):
    def __init__(self,name):
        self.name
=name def eat(self,food): print(%s is eating %s%(self.name,food)) obj1=Dog(hashiqi) obj1.eat(baozi)

正常輸出:hashiqi is eating baozi

增加關鍵字staticmethod:

class Dog(object):
    def __init__(self,name):
        self.name=name
    @staticmethod
    def eat(self,food):
        print(%s is eating %s
%(self.name,food)) obj1=Dog(hashiqi) obj1.eat(baozi)

報錯:

Traceback (most recent call last):
  File "D:/001python/01course/day07/static_method.py", line 11, in <module>
    obj1.eat(baozi)
TypeError: eat() missing 1 required positional argument: food

eat的實參沒有傳給self

結論:增加關鍵字@staticmethod後,類的方法變成了單純的函數,無法訪問類或者實例中的任何屬性,僅增加類名進行調用

如果非要給靜態方法傳類屬性,可以直接將對象傳進去---沒有意義:

class Dog(object):
    def __init__(self,name):
        self.name=name
    @staticmethod
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat(obj1)

輸出:hashiqi is eating

  • 類方法 --關鍵字@classmethod

類方法無法訪問實例屬性

class Dog(object):
    #name=‘yzw‘
    def __init__(self,name):
        self.name=name
    @classmethod
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat()

報錯如下:

    print(%s is eating %(self.name))
AttributeError: type object Dog has no attribute name

類方法只能訪問類屬性:

class Dog(object):
    name=yzw
    def __init__(self,name):
        self.name=name
    @classmethod
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat()

輸入:yzw is eating

  • 屬性方法--關鍵字@property

無法正常使用調用方法

class Dog(object):
    def __init__(self,name):
        self.name=name
    @property
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat()

報錯如下:

    obj1.eat()
TypeError: NoneType object is not callable

改成調用屬性的方法,也就是把括號去掉:

class Dog(object):
    def __init__(self,name):
        self.name=name
    @property
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat

正常輸出:hashiqi is eating

結論:把一個方法變成一個靜態屬性,無法通過()進行調用,它可以通過"對象.屬性"進行調用

屬性普通賦值也會報錯:

class Dog(object):
    def __init__(self,name):
        self.name=name
    @property
    def eat(self):
        print(%s is eating %(self.name))
obj1=Dog(hashiqi)
obj1.eat
obj1.eat=value

error:
    obj1.eat=value
AttributeError: cant set attribute

結論:屬性方法可以通過屬性調用方式獲取,但是不能直接給予賦值

通過特殊處理給屬性方法傳值:

再寫一個同名的方法,使用@xxx.setter關鍵字進行賦值,但是怎麽才能給屬性裏面的形參傳值呢?

class Dog(object):
    def __init__(self,name):
        self.name=name
    @property
    def eat(self):
        print(%s is eating %(self.name))
    @eat.setter
    def eat(self,food):
        print(food)
obj1=Dog(hashiqi)  #正常實例化對象
obj1.eat  # 調用屬性方法
obj1.eat=value‘  #調用屬性賦值方法

hashiqi is eating 
value

屬性傳值二:

通過在構造方法裏增加私有屬性,給屬性方法其他形參傳值

class Dog(object):
    def __init__(self,name):
        self.name=name
        self.__food=None
    @property
    def eat(self):
        print(%s is eating%self.name,self.__food)
    @eat.setter
    def eat(self,food):
        print(food)
        self.__food=food
d=Dog(hashiqi) # 1.正常實例化對象
d.eat   # 2.正常調用屬性方法  輸出:hashiqi is eating None,此時self.__food的值取構造方法的初始值
d.eat=包子  # 3.通過setter屬性賦值方法給方法賦值
d.eat   # 4.再次調用屬性方法,輸出屬性方法的結果,此時屬性方法調用setter裏設置的值

hashiqi is eating None 
baozi
hashiqi is eating baozi 

刪除屬性方法--無法刪除:

class Dog(object):
    def __init__(self,name):
        self.name=name
        self.__food=None
    @property
    def eat(self):
        print(%s is eating %s %(self.name,self.__food))
    @eat.setter
    def eat(self,food):
        print(food)
        self.__food=food
obj1=Dog(hashiqi)
obj1.eat
obj1.eat=baozi
obj1.eat
del obj1.eat

error
AttributeError: cant delete attribute

刪除屬性方法--先刪除私有屬性

class Dog(object):
    def __init__(self,name):
        self.name=name
        self.__food=None
    @property
    def eat(self):
        print(%s is eating %s %(self.name,self.__food))
    @eat.setter
    def eat(self,food):
        print(food)
        self.__food=food
    @eat.deleter
    def eat(self):
        del self.__food
        print(had been deleted)
obj1=Dog(hashiqi)
obj1.eat
obj1.eat=baozi
obj1.eat
del obj1.eat

hashiqi is eating None 
baozi
hashiqi is eating baozi 
had been deleted

刪除再進行調用報錯:

class Dog(object):
    def __init__(self,name):
        self.name=name
        self.__food=None
    @property
    def eat(self):
        print(%s is eating %s %(self.name,self.__food))
    @eat.setter
    def eat(self,food):
        print(food)
        self.__food=food
    @eat.deleter
    def eat(self):
        del self.__food
        print(had been deleted)
obj1=Dog(hashiqi)
obj1.eat
obj1.eat=baozi
obj1.eat
del obj1.eat
obj1.eat  # 依然是去調用靜態方法,此時私有屬性已被刪除

error
    print(%s is eating %s %(self.name,self.__food))
AttributeError: Dog object has no attribute _Dog__food

屬性方法用途:隱藏細節,暴露簡單接口給用戶

案例:查詢航空班次狀態

1.調用航空公司API查詢

2.對查詢結果進行分析

3.將分析後的結果返回頁面,用戶不關心過程/方法,只關心狀態,也就是屬性方法的結果

class Flight(object):
    def __init__(self,name):
        self.fly_name=name
    def checking_status(self):
        print(checking flight %s status...%self.fly_name)
        return 3
    @property
    def Flight_status(self):
        status=self.checking_status()
        if status == 0:
            print(flight had got canceled)
        if status == 1:
            print(flight is arrived)
        if status == 2:
            print(flight has departured already...)
        if status == 3:
            print(cannot confirm the flight status ... check later pls)
    @Flight_status.setter
    def Flight_status(self,status):
        status_dict={0:canceled,1:arrived,2:"departured"}
        print(status has changed to %s%status_dict.get(status))
fly1=Flight(A380)
fly1.Flight_status
fly1.Flight_status = 1

output:
checking flight A380 status...
cannot confirm the flight status ... check later pls
status has changed to arrived

類的特殊成員方法

1.__doc__ 打印類下面的註釋信息

class Class_name(object):
    ‘‘‘class description‘‘‘
    pass
print(Class_name.__doc__)

output:class description

2.__module__ 打印模塊的名字 __class__ 打印類的名字

from fly import Flight
t=Flight(A380)
print(t.__module__)
print(t.__class__)

output:
status has changed to arrived
fly
<class fly.Flight>

3.__init__ 構造方法,實例化類的時候自動創建

4.__del__ 析構方法,一般不定義,系統會自動執行回收垃圾

5.__call__ 對象後面加括號,觸發執行

class Dog(object):
    def __init__(self):
        pass
    def __call__(self, *args, **kwargs):
        print(*args,**kwargs)
d1=Dog()
d1(1,2,3)

output:
1 2 3

6.__dict__ 打印字典形式的類屬性方法或者實例屬性

class Dog(object):
    address=earth
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def func1(self, *args, **kwargs):
        print(*args,**kwargs)
print(Dog.__dict__)  #以字典形式打印類的所有屬性和方法
d1=Dog(hashiqi,19)
print(d1.__dict__)  #以字典形式打印實例的屬性

7.__str__ 如果一個勒種定義了__str__方法,那麽打印對象的時候,默認輸出該方法的返回值

class Dog(object):
    address=earth
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def func1(self, *args, **kwargs):
        print(*args,**kwargs)
    def __str__(self):  # 如果沒有定義str方法,將打印對象的內存地址
        return (return value)

d1=Dog(hashiqi,19)
print(d1)

output:return value

8. item字典方法,使用起來像操縱字典,其實是類內置方法

class Dog(object):
    def __getitem__(self, item):
        print(getitem,item)
    def __setitem__(self, key, value):
        print(setitem,key,value)
    def __delitem__(self, key):
        print(delitem,key)
d1=Dog()  # 1.實例化對象
value1=d1[key1] # 2.調用getitem方法
d1[key2]=value2  # 3.調用setitem方法
del d1[key3]  # 4.調用delitem方法

output:
getitem key1
setitem key2 value2
delitem key3

類的本質

反射

  • hasattr(obj,name_str) 判斷一個對象裏是否有對應的字符串方法
  • getattr(obj,name_str)根據字符串去獲取obj對象裏對應的方法的內存地址
  • setattr(obj,‘y‘,z) 相當於與obj.y=z
  • delattr
class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self):
        print(%s is eating...%self.name)

d1=Dog(hashiqi)
choice =input(input>>).strip()

#判斷有沒有方法
print(hasattr(d1,choice)) #判斷輸入的字符串在內存地址中是否存在
print(getattr(d1,choice)) #獲取內存地址,加括號直接調用
getattr(d1,choice)()

一般這麽用:

class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))

d1=Dog(hashiqi)
choice =input(input>>).strip()  #輸入一個方法,如果方法在類中存在,則未true
if hasattr(d1,choice):
    func=getattr(d1,choice)  #增加一個變量,有助於傳入參數
    func(baozi)  #將參數傳給判斷成功的方法

output:
input>>eat
hashiqi is eating baozi

動態裝進取一個新方法:

class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))
def bulk(self):
    print("%s is yelling"%self.name)
d1=Dog(hashiqi)
choice =input(input>>).strip()  #輸入一個方法,如果方法在類中存在,則未true
if hasattr(d1,choice):
    func=getattr(d1,choice)  #增加一個變量,有助於傳入參數
    func(baozi)  #將參數傳給判斷成功的方法
else:
    setattr(d1,choice,bulk)
    d1.talk(d1)  #相當於調用類裏面的talk方法,talk實際上就是類外面的bulk函數

output:
input>>talk
hashiqi is yelling

動態裝進去一個屬性

class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))
def bulk(self):
    print("%s is yelling"%self.name)
d1=Dog(hashiqi)
choice =input(input>>).strip()  #輸入一個方法,如果方法在類中存在,則未true
if hasattr(d1,choice):
    func=getattr(d1,choice)  #增加一個變量,有助於傳入參數
    func(baozi)  #將參數傳給判斷成功的方法,如果輸入一個已經存在的屬性,則不能加括號調用
else:
    # setattr(d1,choice,bulk)
    # d1.talk(d1)  #相當於調用類裏面的talk方法,talk實際上就是類外面的bulk函數
    setattr(d1,choice,2)
    print(getattr(d1,choice))

output:
input>>asdf
2

刪除一個屬性

class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))
def bulk(self):
    print("%s is yelling"%self.name)
d1=Dog(hashiqi)
choice =input(input>>).strip()  #輸入一個方法,如果方法在類中存在,則未true
if hasattr(d1,choice):
    delattr(d1,choice)
else:
    # setattr(d1,choice,bulk)
    # d1.talk(d1)  #相當於調用類裏面的talk方法,talk實際上就是類外面的bulk函數
    setattr(d1,choice,2)
    print(getattr(d1,choice))

print(d1.name)

output:
print(d1.name)
AttributeError: ‘Dog‘ object has no attribute ‘name‘

再變化

class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(%s is eating %s%(self.name,food))
def bulk(self):
    print("%s is yelling"%self.name)
d1=Dog(hashiqi)
choice =input(input>>).strip()  #輸入一個方法,如果方法在類中存在,則未true
if hasattr(d1,choice):
    getattr(d1,choice)
else:
    setattr(d1,choice,bulk)
    func = getattr(d1,choice) #  這裏不管choice輸入任何東西,都只調用bulk 就是把字符串choice反射成內存中bulk的地址
    func(d1)

異常處理

try:
    可能出錯的語句
except 錯誤關鍵字1 as 別名:  別名捕獲了錯誤的詳細信息
    處理語句
except 錯誤關鍵子2 as 別名:
    處理語句
或者
except (錯誤關鍵字1,錯誤關鍵字2,。。。) as 別名:
    多個錯誤無法定位
except Exception:
    不管什麽錯誤都放到這裏,不建議一開始用
else:
    如果except都沒有捕捉到異常
    就在這裏處理
finally:
    不管有沒有出現錯誤,都會執行

自定義異常

class CustomException(Exception):
    def __init__(self,msg):
        self.msg=msg

try:
    raise CustomException(error) #這裏實例化一個類了
except CustomException as e:  # e保存的就是msg的值
    print(e)

output:
error

python3.x 基礎七:面向對象進階