天天看點

⑤Python面向對象程式設計

⑤Python面向對象程式設計

⑤Python面向對象程式設計

  • ​​Python面向對象程式設計​​
  • ​​1.資料封裝、繼承和多态是面向對象的三大特點。​​
  • ​​2.面向對象程式設計​​
  • ​​3.類與執行個體​​
  • ​​4.資料成員的通路控制​​
  • ​​5.繼承​​
  • ​​6. 多态​​
  • ​​7. 擷取對象資訊​​
  • ​​使用isinstance()​​
  • ​​使用dir()​​
  • ​​8. 執行個體屬性和類屬性​​
  • ​​練習​​

Python面向對象程式設計

1.資料封裝、繼承和多态是面向對象的三大特點。

2.面向對象程式設計

一種程式設計思想,把對象作為程式的基本單元,一個對象包含了資料和操作資料的函數。面向對象的程式設計把計算機程式視為一組對象的集合,而每個對象都可以接受其他對象發過來的消息,并處理這些消息,計算機程式的執行就是一系列消息在各個對象之間傳遞。

3.類與執行個體

class Student(object):
    def __init__(self,name,age):
          self.name=name
          self.age=age
      def print_info():
          print(self.name,self.age)      

執行個體

bart = Student()
Michael = Student('Michael',22)
Michael.print_info()      

4.資料成員的通路控制

在Class内部,可以有屬性和方法,而外部代碼可以通過直接調用執行個體變量的方法來操作資料,這樣就隐藏了内部複雜邏輯。

如果想要讓内部屬性不被外部通路,可以把屬性的名稱前加上兩個下劃線​

​__​

​​,在Python中,執行個體的變量名如果以​

​__​

​開頭,就變成了一個私有變量private,隻有内部可以通路,外部不能通路。

class student(object):
    
    def __init__(self,name,score):
        self.__name = name
        self.__score = score
        
    def print_info(self):
        print(self.__name,self.__score)
        
    def get_name():
        return self.__name
    
    def get_score():
        return self.__score
    
    def set_name(name):
        self.__name = name
        
    def set_score(score):
        self.__score =      

但是實際上還是可以通路的,Python并沒有任何機制防止對私有成員的通路,但是原則上私有成員不可以直接進行通路,全憑自覺。

5.繼承

class Animal(object):
    def run(self):
        print('Animal is running...')
        

class Dog(Animal):
    def run(self):
        print('Dog is running')
        
a = Animal()
d = Dog()
a.run()
b.run()      

子類會繼承父類的方法,并可以對其進行重寫。

6. 多态

多态實際上為了解決動态編譯的問題,Python自動支援多态,并不需要C++中的​

​virtual​

​關鍵字。

def run_twice(animal):
    animal.run()
    animal.run()

>>> run_twice(Animal())
Animal is running...
Animal is running...
>>> run_twice(Dog())
Dog is running...
Dog is running...      

7. 擷取對象資訊

type()

>>> type(123)
     <class 'int'>
     >>> type('str')
     <class 'str'>
     >>> type(None)
     <type(None) 'NoneType'>
     >>> type(123)==type(456)
     True
     >>> type(123)==int
     True
     >>> type('abc')==type('123')
     True
     >>> type('abc')==str
     True
     >>> type('abc')==type(123)
     False      

判斷基本資料類型可以直接寫​

​int​

​​,​

​str​

​​等,但如果要判斷一個對象是否是函數怎麼辦?可以使用​

​types​

​子產品中定義的常量:

>>> import types
  >>> def fn():
  ...     pass
  ...
  >>> type(fn)==types.FunctionType
  True
  >>> type(abs)==types.BuiltinFunctionType
  True
  >>> type(lambda x: x)==types.LambdaType
  True
  >>> type((x for x in range(10)))==types.GeneratorType
  True      

使用isinstance()

對于class的繼承關系來說,使用​

​type()​

​​就很不友善。我們要判斷class的類型,可以使用​

​isinstance()​

​函數。

我們回顧上次的例子,如果繼承關系是:

object -> Animal -> Dog ->      

那麼,​

​isinstance()​

​就可以告訴我們,一個對象是否是某種類型。先建立3種類型的對象:

>>> a = Animal()
     >>> d = Dog()
     >>> h = Husky()      

然後,判斷:

>>> isinstance(h, Husky)
    True      

能用​

​type()​

​​判斷的基本類型也可以用​

​isinstance()​

​判斷:

>>> isinstance('a', str)
    True
    >>> isinstance(123, int)
    True
    >>> isinstance(b'a', bytes)
    True      

并且還可以判斷一個變量是否是某些類型中的一種,比如下面的代碼就可以判斷是否是list或者tuple:

>>> isinstance([1, 2, 3], (list, tuple))
     True
     >>> isinstance((1, 2, 3), (list, tuple))
     True      

使用dir()

如果要獲得一個對象的所有屬性和方法,可以使用​

​dir()​

​函數,它傳回一個包含字元串的list,比如,獲得一個str對象的所有屬性和方法:

>>> dir('ABC')
     ['__add__', '__class__',..., '__subclasshook__', 'capitalize', 'casefold',..., 'zfill']      

類似​

​__xxx__​

​​的屬性和方法在Python中都是有特殊用途的,比如​

​__len__​

​​方法傳回長度。在Python中,如果你調用​

​len()​

​​函數試圖擷取一個對象的長度,實際上,在​

​len()​

​​函數内部,它自動去調用該對象的​

​__len__()​

​方法,是以,下面的代碼是等價的:

>>> len('ABC')
     3
     >>> 'ABC'.__len__()
     3      

我們自己寫的類,如果也想用​

​len(myObj)​

​​的話,就自己寫一個​

​__len__()​

​方法:

>>> class MyDog(object):
    ...     def __len__(self):
    ...         return 100
    ...
    >>> dog = MyDog()
    >>> len(dog)
    100      

僅僅把屬性和方法列出來是不夠的,配合​

​getattr()​

​​、​

​setattr()​

​​以及​

​hasattr()​

​,我們可以直接操作一個對象的狀态:

>>> class MyObject(object):
    ...     def __init__(self):
    ...         self.x = 9
    ...     def power(self):
    ...         return self.x * self.x
    ...
    >>> obj = MyObject()      

緊接着,可以測試該對象的屬性:

>>> hasattr(obj, 'x') # 有屬性'x'嗎?
    True
    >>> obj.x
    9
    >>> hasattr(obj, 'y') # 有屬性'y'嗎?
    False
    >>> setattr(obj, 'y', 19) # 設定一個屬性'y'
    >>> hasattr(obj, 'y') # 有屬性'y'嗎?
    True
    >>> getattr(obj, 'y') # 擷取屬性'y'
    19
    >>> obj.y # 擷取屬性'y'
    19      

如果試圖擷取不存在的屬性,會抛出AttributeError的錯誤:

>>> getattr(obj, 'z') # 擷取屬性'z'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'MyObject' object has no attribute 'z'      

可以傳入一個default參數,如果屬性不存在,就傳回預設值:

>>> getattr(obj, 'z', 404) # 擷取屬性'z',如果不存在,傳回預設值404
    404      
>>> hasattr(obj, 'power') # 有屬性'power'嗎?
    True
    >>> getattr(obj, 'power') # 擷取屬性'power'
    <bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
    >>> fn = getattr(obj, 'power') # 擷取屬性'power'并指派到變量fn
    >>> fn # fn指向obj.power
    <bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
    >>> fn() # 調用fn()與調用obj.power()是一樣的
    81      

8. 執行個體屬性和類屬性

class Student(object):
      def __init__(self,name):
          self.name = name
          
  class Student1(object):
      name = 'Student'#類屬性,對所有對象共享      

練習

class Student(object):
       count = 0
   
       def __init__(self, name):
           self.name = name
           Student.count+=1