day08面向對象(二)

Python 面向對象

 本章內容簡介:

1. 類的成員:
    1) 字段 : 普通字段、靜態字段;python

    2) 方法 : 普通方法、靜態方法、類方法;編程

    3) 屬性 : 普通屬性(獲取、設置、刪除);設計模式

2. 成員修飾符:app

    1)公有的       任何 均可以調用;框架

    2)私有的       僅類本身內部能夠調用;能夠用一個另類的方法調用,就是 obj._類名__私有(字段等),好吧,知道能這麼用就好了,最好忘了它。函數

3. 類的特殊成員:ui

    __init__      構造方法;  spa

    __dic__      註釋文檔查看,函數下加引號寫的第一位置,會被此成員讀取;設計

    __call__      變量加括號執行call方法;指針

    __str__      將內存地址的內容,讀取成str內容;     

    __setitem__    

    ......

4. 面向對象的其它內容:

    -- isinstance    判斷一個對象是否屬於某個類;

    -- issubclass    判斷一個類是否屬於某個類的子類;

    -- 執行父類構造方法

    -- 應用:

        自定義類型,對字典進行補充,有序字典,源碼的擴展;

5. 設計模式之單例模式;

6. 異常處理:

    try  ===  except === = finally

一. 類的成員

  • 字段

1. 普通字段,實例:

class Foo:
    def __init__(self,name):
        self.name = name

代碼解析:

  name就是普通字段,當Foo函數,被實例化時,如:obj = Foo('hailong') ,對象obj 就使用了name普通字段,普通字典默認被對象使用,因此普通字段是保存在對象裏的;

2. 靜態字段,實例:

class Province:
    country = "中國" # 靜態字段,保存在類裏,節省內存空間;

    def __init__(self,name):
        self.name = name

country = Province.country
tj = Province("天津")

print(tj.country ,'\t',country)

代碼解析:

  country是靜態字段,如上實例所示,靜態字段,類能夠調用,對象也能夠調用,其它語言裏是不容許的,之因此對象能夠調用靜態字段,是由於對象裏的類對象指針(對象去數據時,是先從本身自己找,找不到,經過類對象指針到類裏找)經過這種方式來訪問的;一般狀況下,咱們要使用類來調用靜態字段;

總結:

  普通字段,用對象來訪問; 靜態字段,使用類來訪問,實在沒辦法時才用對象訪問;

  當執行程序時,若是沒建立對象時,普通字段不會加載到內存,可是靜態字段默認會加載到內存;

  •  方法

1. 普通方法,實例:

class Province:
    country = "中國" 

    def __init__(self,name):
        self.name = name

    def show(self):  # 方法屬於類,是由對象調用的
        print(self.name)

tj = Province("天津")
tj.show()

代碼解析:

  方法屬於類,普通方法存在類裏,是由對象調用的;

2. 靜態方法,實例:

class Province:
    country = "中國" # 靜態字段,保存在類裏,節省內存空間;

    def __init__(self,name):
        self.name = name

    @staticmethod    # 靜態方法,是由類調用的
    def func(arg1,arg2):
        print(arg1,arg2)

Province.func(123,'qcc'

代碼解析:

  靜態方法是由類調用的,就是方法去掉self參數後,是用裝飾器staticmethod,傳參自定義,不須要建立對象,就能夠執行的方法。用於一些不通用的方法,這樣節省內存空間;

  至關於Python的函數;

3. 類方法,實例:

class Province:
    country = "中國" # 靜態字段,保存在類裏,節省內存空間;

    def __init__(self,name):
        self.name = name

    @classmethod
    def f1(cls):
        print(cls)

Province.f1()

代碼解析:

  類方法是由類調用的,它有一個默認的形式參數cls,cls至關於類名;

  • 屬性

1. 普通屬性,實例:

class Pager:
    def __init__(self,count_pager):
        self.count_pager = count_pager

    @property  # 普通屬性
    def all_pager(self):
        a1,a2=divmod(self.count_pager,10)
        if a2 == 0:
            return a1
        return a1+1

p = Pager(101)
print(p.all_pager)  # 執行普通屬性,不用加括號了

代碼解析:

  普通屬性,具備方法的訪問寫形式,具備字段的訪問形式。 至關於方法去掉括號,由對象調用;

2. 屬性操做(設置)實例:

class Pager:
    def __init__(self,count_pager):
        self.count_pager = count_pager

    @property
    def all_pager(self):
        a1,a2=divmod(self.count_pager,10)
        if a2 == 0:
            return a1
        return a1+1

    @all_pager.setter
    def all_pager(self,value):
        print(value)

p = Pager(101)
p.count_pager = 211  # 設置屬性,對屬性的方法進行setter;
print(p.count_pager)

代碼解析:

  對象生成後,count_pager 根據類參數定義一個值,當想要使用一個新值時,須要使用到設置屬性,給字段count_pager從新賦值,使用普通屬性方法setter裝飾器,從新給字段賦值;

3. 屬性操做(刪除)實例:

class Pager:
    def __init__(self,count_pager):
        self.count_pager = count_pager

    @property
    def all_pager(self):
        a1,a2=divmod(self.count_pager,10)
        if a2 == 0:
            return a1
        return a1+1

    @all_pager.setter
    def all_pager(self,value):
        print(value)

    @all_pager.deleter
    def all_pager(self):
        print("del all_pager")

p = Pager(101)
p.count_pager = 211 #設置方法,會調用all_pager.setter下的方法;
print(p.count_pager)  
del p.all_pager # del 是個語法,會調用all_pager.deleter下的方法;

property的構造方法中有個四個參數

  • 第一個參數是方法名,調用 對象.屬性 時自動觸發執行方法
  • 第二個參數是方法名,調用 對象.屬性 = XXX 時自動觸發執行方法
  • 第三個參數是方法名,調用 del 對象.屬性 時自動觸發執行方法
  • 第四個參數是字符串,調用 對象.屬性.__doc__ ,此參數是該屬性的描述信息

屬性的另外一種寫法

class Pager:
    def __init__(self,name):
        self.name = name

    def f1(self):
        return 123

    def f2(self,value):
        print(value)

    def f3(self):
        print('del f1') # 還沒弄明白,具體怎麼用

    foo = property(fget=f1,fset=f2,fdel=f3)

obj = Pager('hailong')
res = obj.foo
print(res)
obj.foo = 456
del obj.foo

代碼解析:

  不用加裝飾器了,直接給靜態字段賦值,使用property,來完成屬性的功能; 

由屬性的定義和調用要注意一下幾點:

  • 定義時,在普通方法的基礎上添加 @property 裝飾器;
  • 定義時,屬性僅有一個self參數
  • 調用時,無需括號
               方法:foo_obj.func()
               屬性:foo_obj.prop

注意:屬性存在乎義是:訪問屬性時能夠製造出和訪問字段徹底相同的假象

         屬性由方法變種而來,若是Python中沒有屬性,方法徹底能夠代替其功能。

二.  成員修飾符

 1. 公有的,實例:

class Province(object):

    def __init__(self,name):
        self.name = name


hb = Province("河北")
print(hb.name)  #name是公有的,任何對象均可以調用;

代碼解析:

  這個例子裏,name就是公共的,任何基於Province建立的對象都能使用;

2. 私有修飾符,實例(一):

class Province(object):

    def __init__(self,name):
        self.__name = name

    def f1(self):
        print(self.__name)

hb = Province("河北")
hb.f1()

# print(hb.__name) # 報錯 AttributeError: 'Province' object has no attribute '__name'

代碼解析:

  當把公有的,加上雙下劃線後,就變成私有的了,這時外部不能調用,只能是類裏的方法能夠調用;只有本身訪問能夠,不能被繼承;

實例(二):

class Province(object):
    __paw = 123
    def __init__(self,name):
        self.__name = name

    def f1(self):
        print(Province.__paw)

    @staticmethod
    def f2():
        print(Province.__paw)

hb = Province("河北")
hb.f1()       # 經過變量調用使用了私有字段的方法;
Province.f2() #直接用類調用,靜態方法裏的私有字段;
hb.f2()  # 也能夠成功,可是不建議這樣使用;
Province.f1() # 不能夠在外部直接使用類裏的私有字段,報錯 TypeError: f1() missing 1 required positional argument: 'self'

三. 特殊成員

上文介紹了Python的類成員以及成員修飾符,從而瞭解到類中有字段、方法和屬性三大類成員,而且成員名前若是有兩個下劃線,則表示該成員是私有成員,私有成員只能由類內部調用。不管人或事物每每都有不按套路出牌的狀況,Python的類成員也是如此,存在着一些具備特殊含義的成員,詳情以下:

1. del、call 和  str方法:

class Foo(object):

    instance = None
    def __init__(self,name,age):
        self.name=name
        self.age = age

    # 析構方法,系統垃圾回收以前執行這個方法;
    def __del__(self):
        pass

    #
    def __call__(self, *args, **kwargs):
        print("call")

    #
    def __str__(self):
        return "%s - %s" % (self.name,self.age)

obj = Foo("hailong",23)
obj1 = Foo("eric",23)
print(obj)       # 執行時,調用了str方法
res = str(obj1)  # 執行時,調用了str方法
obj()  # 變量加括號,執行call方法;
Foo("hailong",23)() # 類執行,加括號執行call方法;
print(obj1)

2. add 、 dict 方法:

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age  = age

    def __add__(self, other):
        temp = "%s - %d" % (self.name,other.age)
        return temp

obj1= Foo("hailong",23)
obj2= Foo('eric',19)
res = obj1 + obj2     # 執行add方法;
print(res)
print(obj1.__dict__)  # 返回obj1封裝的內容,字典格式輸出;

若是執行  類.__dict__ 會打印出類裏封裝的全部的成員,通常用於對象的封裝查看;

3. getitem、setitem和delitem方法:

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age  = age

    def __getitem__(self, item):
        return 123

    def __setitem__(self, key, value):
        print(key,value)

    def __delitem__(self, key):
        print("del %s" % key)

obj1= Foo("hailong",23)
res = obj1['abc']  # 執行getitem方法
print(res,"----")
obj1['k1'] = 122   # 執行了setitem方法 ,執行結果是k1 122
print(obj1.__dict__) # obj1沒有任何改變;
del obj1['k1']      # 執行delitem方法,

對象後加括號執行call方法,加上中括號執行 getitem方法。。。

4. getitem 切片方法:

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age  = age

    def __getitem__(self, item):
        print(item.start)
        print(item.stop)
        print(item.step)
        return 123

    def __setitem__(self, key, value):
        print(key,value)

obj1= Foo("hailong",23)
# res = obj1['abc']  # 字符串方法沒有切片start等位置屬性;
res1 = obj1[0:4:2]

5. iter 迭代 方法:

用於迭代器,之因此列表、字典、元組能夠進行for循環,是由於類型內部定義了 __iter__ 

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age  = age

    def __iter__(self):   # iter方法
        return iter([11,22,33,44])  # 可迭代類型;

obj = Foo("hailong",23)
for item in obj:   
    print(item)

for循環,例子二:

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age  = age

    def __iter__(self):
        yield 1
        yield 2

obj = Foo("hailong",23)
for item in obj:
    print(item)

6.  __module__ 和  __class__ 

  __module__ 表示當前操做的對象在那個模塊

  __class__     表示當前操做的對象的類是什麼

四. 面向對象的其它內容 

1. isinstance 和 issubclass 內置變量;

class Foo:
    pass

class Func(Foo):
    pass

obj = Foo()
res = isinstance(obj,Foo) # obj  是 基於Foo類建立的,返回True;
print(res)
ret = issubclass(Func,Foo) # Func 類是 Foo類的一個子類,返回True;
print(ret)

2.  執行父類構造方法;

如何執行,看實例:

class Foo:
    def f1(self):
        print("Foo.f1")

class Func(Foo):
    def f1(self):
        super(Func,self).f1()
        print('Func.f1')

obj = Func()
res = obj.f1() # obj 執行的了本身的f1方法也執行了父類裏的f1方法,由於有super;

這個方法應用於:當想要使用其它程序的功能或框架裏的方法時,繼承框架或功能的類方法,使用super就能使用框架的功能了;

3. 有序字典:

class Mydict(dict):

    def __init__(self):
        self.li = []
        super(Mydict,self).__init__()

    def __setitem__(self, key, value):
        self.li.append(key)
        super(Mydict,self).__setitem__(key,value)

    def __str__(self):
        temp_li = []
        for key in self.li:
            value = self.get(key)
            temp_li.append("'%s':%s" %(key,value))
        temp_str = "{" + ",".join(temp_li) + "}"
        return temp_str


obj = Mydict()
obj['k1'] = 123
obj['k2'] = 456
print(obj)

代碼解析:

  繼承字典的類,將正常生成字典的key,添加到一個空列表,經過自定義類型對字典的生成過程從新定義,將無序存儲的字典,寫成一個列表,根據字符串拼接的方法,讀取成有序的字典;

五. 設計模式之單例模式

用來建立單個實例,何時用?  無論獲取多少個實例,他們的內存地址是同樣的;

class Foo:
    instance = None
    def __init__(self,name):
        self.name = name

    @classmethod
    def get_instance(cls):
        if cls.instance:
            return cls.instance
        else:
            obj = cls('hailong')
            cls.instance = obj
            return obj

obj1 = Foo.get_instance()
obj2 = Foo.get_instance() # 無論獲取多少個實例,他們的內存地址是同樣的;
print(obj1,obj2) # 兩個對象內存地址相同;

六. 異常處理

try --->except  try內容若是不報錯,永遠不會執行except的內容;

一、異常基礎

在編程過程當中爲了增長友好性,在程序出現bug時通常不會將錯誤信息顯示給用戶,而是現實一個提示的頁面,通俗來講就是不讓用戶看見大黃頁!!!

try:
    pass
except Exception,ex:
    pass

 

需求:將用戶輸入的兩個數字相加

while True:
    num1 = input('input num1:')
    num2 = input('input num2:')
    try:
        num1 = int(num1)
        num2 = int(num2)
        result = num1 + num2
        try:
            print(result)
        except NameError as A:
            print(A)
    except Exception as E:
        print(E)

二、異常種類

python中的異常種類很是多,每一個異常專門用於處理某一項異常!!!

1) 經常使用異常:

AttributeError 試圖訪問一個對象沒有的樹形,好比foo.x,可是foo沒有屬性x
IOError 輸入/輸出異常;基本上是沒法打開文件
ImportError 沒法引入模塊或包;基本上是路徑問題或名稱錯誤
IndentationError 語法錯誤(的子類) ;代碼沒有正確對齊
IndexError 下標索引超出序列邊界,好比當x只有三個元素,卻試圖訪問x[5]
KeyError 試圖訪問字典裏不存在的鍵
KeyboardInterrupt Ctrl+C被按下
NameError 使用一個還未被賦予對象的變量
SyntaxError Python代碼非法,代碼不能編譯(我的認爲這是語法錯誤,寫錯了)
TypeError 傳入對象類型與要求的不符合
UnboundLocalError 試圖訪問一個還未被設置的局部變量,基本上是因爲另有一個同名的全局變量,
致使你覺得正在訪問它
ValueError 傳入一個調用者不指望的值,即便值的類型是正確的

對於特殊處理或提醒的異常須要先定義,最後定義Exception來確保程序正常運行。

2)另外一種結構的異常:

try:
    # 主代碼塊
    pass
except KeyError as ex:
    # 異常時,執行該塊
    pass
else:
    # 主代碼塊執行完,執行該塊
    pass
finally:
    # 不管異常與否,最終執行該塊
    pass

3) 主動拋出異常:

try:
    raise Exception('錯誤了。。。')
except Exception as ex:
    print(ex)

4) 自定義異常:

class WupeiqiException(Exception):
 
    def __init__(self, msg):
        self.message = msg
 
    def __str__(self):
        return self.message
 
try:
    raise WupeiqiException('個人異常')
except WupeiqiException as e:
    print(e)

5)斷言

# assert 條件
 
assert 1 == 1
 
assert 1 == 2

 

條件成立執行,不成立就不執行;

________________________________________________________END____________________________________________________

相關文章
相關標籤/搜索