1. 程式人生 > >Python 3學習 ——面向對象

Python 3學習 ——面向對象

append weakref fun 方式 pen count ESS 類型 --

Python 學習——面向對象

寫此博客 是為了激勵自己,並且將自己的心得以及遇到的問題與人分享

一、面向對象基礎

                面向對象就是一個類和對象的應用。

  1.定義方法:

----------------------------------------------------------------

    class 類名:

      def 方法名(self , arg):

      print(arg)

    中間人 = 類名()

    中間人.方法名(arg)

----------------------------------------------------------------

self 代指,調用方法的 對象 (中間人)

  2.構造方法:類名加()自動執行構造方法

 1 class Person:
 2     def __init__(self,name,age):
 3         self.n = name
 4         self.a = age
 5     def show(self):
 6         print("%s  %s " %(self.n,self.a))
 7 
 8 liufeiduo = Person(劉飛鐸,19)
 9 liufeiduo.show()
10 
11 chengjunfei = Person(
程俊飛,18) 12 chengjunfei.show()

  3.繼承

 1 class Father:   # 父類,基類
 2     def 籃球(self):
 3         pass
 4     def 足球(self):
 5         pass
 6     def 抽煙(self):
 7         pass
 8 
 9 class Son(Father):  # 子類,派生類
10     def 排球(self):
11         pass
12 
13 
14 s = Son()
15 s.籃球()

  子類重寫父類方法

 1 class
F: 2 def f1(self): 3 print(F,f1) 4 def f2(self): 5 print(F,f2) 6 7 class S(F): 8 def s1(self): 9 print(S,s1) 10 def f2(self): 11 print(S,s2) 12 13 obj = S() 14 obj.s1() #S,s1  s1中的self 是形參,此時代指 obj 15 obj.f2() #S,s2   

  self 永遠指調用方法的調用者

  兩種調用父類的方法:

          方法一: super
class
F: def f1(self): print(F,f1) def f2(self): print(F,f2) class S(F): def s1(self): print(S,s1) def f2(self): super(S,self).f2() #執行父類中的f2方法 #super代指了它的父類 print(S,s2) obj = S() obj.f2() ‘‘‘ F,f2 S,s2 ‘‘‘
          方法二:通過父類名調用方法
class
F: def f1(self): print(F,f1) def f2(self): print(F,f2) class S(F): def s1(self): print(S,s1) def f2(self): #super(S,self).f2() #執行父類中的f2方法 #super代指了它的父類 print(S,s2) F.f2(self) obj = S() obj.f2() ‘‘‘ S,s2 F,f2 ‘‘‘

  多繼承:Python 與 C++ 獨有支持多繼承,一個子類可以繼承多個父類。

 1 class F1:
 2     def a(self):
 3         print(F1.a)
 4 
 5 class F2:
 6     def a(self):
 7         print(F2.a)
 8 
 9 class Son(F1,F2):   # 按照從左到右的順序,"一條路找到黑的順序"來進行找。 如果有同一個根時,根最後執行。
10     pass
11 
12 obj = Son()
13 obj.a()     #F1.a

  4.多態

1 def func(arg):
2     print(arg)
3                  #   Python 中的原生多態,不被類型所限定。
4 func(1)
5 
6 func(llalala)

二、面向對象中級

  1.類成員

    字段

      普通字段,保存在對象中,執行只能通過對象訪問。

      靜態字段,保存在類中,在內存中只保存一份,執行時可以通過對象訪問也可以通過類進行訪問。

1 class Provience:
2     country = 中國
3 
4     def __init__(self,name):
5         self.name = name
6 henan = Provience(河南)
7 print(Provience.country)    #中國
8 print(henan.name)    #河南

    方法

      普通方法,保存在類中,由對象來進行調用。self --> 對象

      靜態方法,保存在類中,由類直接調用。

      類方法,保存在類中,由類直接調用。cls --> 當前類

 1 class Foo:
 2 
 3     def bar(self):  #普通方法
 4         print(bar)
 5 
 6     @staticmethod
 7     def sta(a1,a2):  #靜態方法   self 就不是必須存在的了
 8         print(a1,a2)
 9 
10     @classmethod
11     def classmd(cls):  #類方法  cls 是類名 不依賴對象 可以通過類直接執行
12         print(cls)
13         print(classmd)
14 
15 object = Foo()
16 object.bar()    #bar
17 
18 Foo.sta(2,4)   #2 4 調用者直接類調用就可以了
19 
20 Foo.classmd()    # <class ‘__main__.Foo‘>  classmd

  應用場景:

      如果對象中需要保存一些值,執行某功能時,需要使用對象中的值 ---> 普通方法。

      不需要任何對象中的值 ---> 靜態方法。

  類的成員——屬性:按照方法的方式寫,按照字段調用的方式調用。

 1 class Foo:
 2     def __init__(self):
 3         self.name = a
 4 
 5     def bar(self):
 6         print(bar)
 7 
 8     @property  #通過property裝飾器
 9     def per(self):  # 屬性:  偽造成方法,但訪問的時候使用的是字段的方式
10         print(per)
11 
12 obj = Foo()
13 obj.per

  利用 屬性 完成分頁的功能:

class Pergination:

    def __init__(self,current_page):
        self.page = int(current_page)

    @property
    def start(self):
        val = (self.page - 1) * 10
        return val
    @property
    def end(self):
        val = self.page * 10
        return val
li = []

for i in range(1000):
    li.append(i)

while True:
    p = input(請輸入要查看的頁碼: )#     每頁顯示十條
    obj = Pergination(p)

    print(li[obj.start:obj.end])

三、面向對象高級

  1. 成員修飾符

    公有成員

    私有成員   __字段名

      - 無法直接訪問,只能間接訪問

      - 繼承過來的私有字段是無法進行訪問,內部訪問指的是自身內部,繼承過來的不可以。

 私有字段
1
class Foo: 2 3 def __init__(self,name,age): 4 self.name = name 5 # self.age = age 6 self.__age = age # 私有,外部無法直接進行訪問 7 8 def show(self): #間接訪問私有字段方法 9 return self.__age 10 11 obj = Foo(chengjunfei,20) 12 print(obj.name) 13 print(obj.show()) #間接訪問私有字段

  2. 特殊成員

    __init__ 類()  自動執行

    __call__ 對象() 類()()自動執行

 1 class Foo:
 2 
 3     def __init__(self):
 4         print(init)
 5 
 6     def __call__(self,*args,**kwargs):
 7         print(call)
 8 
 9 
10 
11 Foo()() #init  call
12 
13 object = Foo()
14 object()    #對象後面加括號會執行 __call__ 中的方法,Python的一個內置語法。

    __int__ int(對象)

    __str__ str(對象)

    __add__

 1 class Foo:
 2     def __init__(self):
 3         pass
 4 
 5     def __add__(self, other):
 6         return 123
 7 
 8 obj1 = Foo()
 9 obj2 = Foo()
10 
11 r = obj1 + obj2
12 # 兩個對象相加時,自動執行第一個對象的__add__方法,並且將第二個對象當作參數傳遞進去。
13 
14 print(r,type(r))    #123 <class ‘int‘>

    __del__   析構方法,當對象被銷毀時,自動執行。

    __dict__   將對象中封裝的所有內容通過字典的形式返回。

 1 class Foo:
 2 
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6 
 7 object = Foo(劉飛鐸,21)
 8 
 9 d = object.__dict__
10 print(d)    #{‘name‘: ‘劉飛鐸‘, ‘age‘: 21}
11 
12 c = Foo.__dict__
13 print(c)    #{‘__module__‘: ‘__main__‘, ‘__init__‘: <function Foo.__init__ at 0x0000016D6A1499D8>,
14             #  ‘__dict__‘: <attribute ‘__dict__‘ of ‘Foo‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Foo‘ objects>,
15             #  ‘__doc__‘: None}

    __getitem__  # 切片(slice類型)或者索引    有返回值

    __setitem__  沒有返回值

    __delitem__  沒有返回值

 1 class Foo:
 2 
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6 
 7     def __getitem__(self, item):
 8         return item + 10
 9 
10     def __setitem__(self, key, value):
11         print(key)
12         print(value)
13 
14     def __delitem__(self, key):
15         print(key)
16 
17 
18 li = Foo(Liufeiduo,22)
19 r = li[8]   #自動執行li對象中的__getitem__方法,8當作參數傳遞給了item
20 
21 print(r)    #18
22 
23 li[100] = asdf    # def __setitem__(self, key, value):
24 del li[985]     # def __delitem__(self, key):

    __iter__ :如果類中有 __iter__ 方法,對象 ---> 可叠代對象。

         對象.__iter__ ()的返回值,就是叠代器。

         for 循環 遇到 叠代器,就執行 next( ) 方法就行了。

         for 循環 遇到 可叠代對象,要先通過 可叠代對象.__iter__ ( )方法獲取叠代器然後繼續執行next( )方法。

 1 class Foo:
 2 
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6     def __iter__(self):
 7         return iter([11,22,33,44])
 8 
 9 li = Foo(liufeiduo,22)
10 #1.獲取li對象的類 Foo 中的__iter__ 方法,並獲取其返回值。
11 #2.去循環上一步中返回的對象。
12 for i in li:
13     print(i)    # 11/r 22/r 33/r 44/r

  3. metaclass 類的祖宗

    a. 在Python中,一切事物都是對象。

    b.

      class Foo():

        pass

      obj = Foo()

      # obj 是對象,Foo 是類。

      # Foo 類也是一個對象,type 的對象。

    c. 類都是 type 類的對象 type(...)

     "對象"都是類的對象 類()

 1 class MyType(type):
 2     def __init__(self,*args,**kwargs):
 3         print(123)
 4         pass
 5 
 6 
 7 class Foo(object,metaclass=MyType):
 8     def func(self):
 9         print(hello)
10 
11 # 執行結果:  123

  類後面加括號,創建對象並不是直接執行了該類的 __init__ 方法,先執行 type 的 __call__ 方法,再執行該類的 __new__ 方法,再然後執行了 __init__ 方法。

技術分享圖片

  

  4. 異常處理

 1 #-----------------最基本的---------------------
 2 while True:
 3     try:
 4         inp = input(請輸入序號:)
 5         # 代碼塊,邏輯
 6         i = int(inp)
 7     except Exception as e:
 8         # e 是Exception的對象,對象中封裝了錯誤信息。
 9         # 上述代碼塊出錯,自動執行當前塊內容。
10         print(e)
11         i = 1
12 
13     print(i)
14 
15 #--------------寫異常的基本流程--------------------------------
16     try:
17         int (w3rs)
18     except IndexError as e:
19         print(IndexError,e)
20     except ValueError as e:
21         print(ValueError,e)
22     except Exception as e:
23         print(Exception,e)
24 
25     else:
26         print(else)
27 
28     finally:
29         print(....)
30 #--------------------------------------------

    寫異常時,先 except ‘小弟’,後寫‘大哥’,else 後面是沒有捕捉到錯誤時執行,finally 後是無論如何都會執行。

  主動拋出異常

1 try:
2     raise Exception(我是主動拋出的異常)  # 主動觸發異常
3 except Exception as e:
4     print(e)
5     # 執行結果:我是主動拋出的異常

  主動觸發異常的小應用(記錄錯誤日誌)

 1 def db():
 2    #return True
 3     return False
 4 
 5 def index():
 6     try:
 7         result = db()
 8         if not result:
 9             #打開文件,寫日誌
10             raise Exception(數據庫處理錯誤)  #當數據庫返回值為False時,主動拋出異常,記錄日誌。
11 
12     except Exception as e:
13         str_error = str(e)
14         print(str_error)
15         #打開文件寫日誌
16         
17 index()

  自定義異常

 1 class LfdError(Exception):
 2 
 3     def __init__(self,msg):
 4         self.message = msg
 5 
 6     def __str__(self):
 7         return self.message
 8 
 9 obj = LfdError(liufeiduo)
10 print(obj)
11 
12 try:
13     raise LfdError(我錯了)
14 except LfdError as e:
15     print(e)

  斷言  assert + 條件 如果滿足條件,繼續執行,若不滿足條件,直接報錯。用於強制用戶服從,不服從就報錯,可捕獲但一般不捕獲。

  5. 反射

    在Python 中執行反射效率蠻高的。

  通過字符串的形式操作對象中的成員:

    ①getattr方法,到某某東西中獲取某某內容。

 1 class Foo:
 2     def __init__(self,name,age):
 3         self.name = name
 4         self.age = age
 5 
 6     def show(self):
 7         return "%s-%s" %(self.name,self.age)
 8 object = Foo(liufeiduo,22)
 9 
10 # b = "name"
11 # print(object.__dict__[b])
12 inp = input(>>>>>>>>>>)
13 #去什麽東西裏面獲取什麽內容
14 b = getattr(object,inp)
15 
16 print(b)    #liufeiduo

    ②hasattr方法,去檢測對象中是否有某成員,返回True、False。

    ③setattr方法,在對象中主動設置某個值。

 1 class Foo:
 2     def __init__(self,name,age):
 3         self.name = name
 4         self.age = age
 5 
 6     def show(self):
 7         return "%s-%s" %(self.name,self.age)
 8 object = Foo(liufeiduo,22)
 9 
10 
11 setattr(object,love,chengjunfei)
12 print(object.love)  #chengjunfei

    ④delattr方法,將主動設置的某個值刪除掉。

    反射在模塊之間也是可以用的。

  6.單例模式

class Foo:

    __v = None

    @classmethod
    def get_instance(cls):
        if cls.__v:
            return cls.__v

        else:
            cls.__v = Foo()
            return cls.__v

object1 = Foo.get_instance()
print(object1)
object2 = Foo.get_instance()
print(object2)

#          執行結果:
#<__main__.Foo object at 0x000001137E007908>
#<__main__.Foo object at 0x000001137E007908>

  好處:內存中對象只創建一份就可以了,

Python 3學習 ——面向對象