Python學習--面向對象編程

1、編程範式

編程範式:按照什麼方式來去編程,去實現一個功能。舉個例子:作飯能夠用電磁爐,也能夠用燃氣竈。不一樣的編程範式本質上表明對各類類型的任務採起的不一樣的解決問題的思路,兩種最重要的編程範式分別是面向過程編程和麪向對象編程。python

2、兩大編程範式

一、面向過程編程

面向過程的思想是把一個項目、一件事情按照必定的順序,從頭至尾一步一步地作下去,先作什麼,後作什麼,一直到結束。這種思想比較好理解,其實這也是一我的作事的方法,咱們以前編程的思想也都是使用這種思想。這種編程思想只要前面有一個步驟變了,那麼後面的就也要變,維護成本高。編程

面向過程多用於編寫一次性腳本或代碼量極少的簡單小程序。小程序

二、面向對象編程

面向對象--Object Oriented Programming,簡稱oop。面向對象的思想是把一個項目、一件事情分紅更小的項目,或者說分紅一個個更小的部分,每一部分負責什麼方面的功能,最後再由這些部分組合而成爲一個總體。這種思想比較適合多人的分工合做,就像一個大的機關:分各個部門,每一個部門分別負責某樣職能,各個部門能夠不用理解其餘部門的事,只要完成本身那一部分的事情就OK了。函數式編程

3、面向對象的優勢

對於編程初學者來說,OOP不是一個很容易理解的編程方式,雖然你們都很清楚概念以及語法,可是一到真正寫程序的時候,仍是喜歡用函數式編程來寫代碼。特別是初學者,很容易陷入一個窘境就是「我知道面向對象,我也會寫類,但我依然沒發如今使用了面向對象後,對咱們的程序開發效率或其它方面帶來什麼好處,由於我使用函數編程就能夠減小重複代碼並作到程序可擴展了,爲啥子還用面向對象?」不管用什麼形式來編程,咱們都要明確記住如下原則:函數

一、寫重複代碼是很是很差的低級行爲oop

二、你寫的代碼須要常常變動spa

開發正規的程序跟寫個運行一次就扔了的小腳本一個很大不一樣就是:你的代碼老是須要不斷的更改,不是修改bug就是添加新功能等。因此爲了之後更方便程序的修改及擴展,代碼必定要遵循易讀、易改的原則(專業數據叫可讀性好、易擴展)。code

函數的出現幫咱們輕鬆的解決重複代碼的問題,其實OOP編程的主要做用也是使你的代碼修改和擴展變的更容易,易維護、減小代碼量對象

那麼要問了,函數都能實現這個需求了,還要OOP幹什麼用? 呵呵,說這話就像古時候,人們打仗殺人都用刀,後來出來了槍,它的功能跟刀同樣也是殺人。而後小白就問,既然刀能殺人了,那還要槍有什麼用。顯而易見,由於槍能更好更快更容易的殺人。函數編程與OOP的主要區別就是OOP可使程序更加容易擴展和易更改。blog

4、面向對象特性

面向對象的三大特性:封裝、繼承、多態

一、類:class

類,對比現實世界來講就是一個種類,一個模型。一個類便是對一類擁有相同屬性的對象的抽象、藍圖、原型。

在類中定義了這些對象的都具有的屬性(variables(data))、共同的方法。類由屬性和方法組成,類的屬性是對數據的封裝,而類的方法是對類的行爲的封裝

例:鳥類的相同的屬性就包含:有翅膀,會飛,能吃,能叫,就能夠抽取出一個藍圖原型爲鳥類

二、對象:object

對象,也就是指模型造出來的具體的東西

一個對象便是一個類的實例化後實例,一個類必須通過實例化後纔可在程序中調用,一個類能夠實例化多個對象,每一個對象亦能夠有不一樣的屬性。就像人類是指全部人,每一個人是指具體的對象,人與人以前有共性,亦有不一樣。

三、實例化

初始化一個類,造了一個對象。把一個類變成一個具體的對象的過程,叫作實例化。

四、封裝

把一些功能的實現細節不對外暴露,類中對數據的賦值、內部調用對外部用戶是透明的,這使類變成了一個膠囊或容器,裏面包含着類的數據和方法。

好比說造的一我的,你把他身體內部的什麼心肝脾肺腎都封裝起來了,其餘人都看不到,你直接找這我的。

五、繼承

一個類能夠派生出子類,在這個父類裏定義的屬性、方法自動被子類繼承。好比說你繼承了你父親的姓。

python3中多繼承都是廣度優先,python2中經典類的多繼承是深度優先,新式類的多繼承是按照廣度優先的。

繼承是爲了代碼的重用

六、多態

對不一樣類的對象發出相同的消息將會有不一樣的行爲。一種接口,多種實現

好比:你的老闆讓全部員工在九點鐘開始工做, 他只要在九點鐘的時候說:「開始工做」便可,而不須要對銷售人員說:「開始銷售工做」,對技術人員說:「開始技術工做」, 由於「員工」是一個抽象的事物, 只要是員工就能夠開始工做,他知道這一點就好了。至於每一個員工,固然會各司其職,作各自的工做。

多態就是抽象化的一種體現,把一系列具體事物的共同點抽象出來, 再經過這個抽象的事物, 與不一樣的具體事物進行對話。

爲何要用多態?應用程序沒必要爲每個子類編寫功能調用,只須要對抽象基類進行處理便可。大大提升程序的可複用性。

5、類

一些概念:

屬性:屬性就是類裏面的一個變量,有類變量和實例變量。類變量是類在定義的時候就有的,實例變量是在實例化的時候才產生的變量。這個能夠理解爲,人是一個類,他的名字、年齡、性別就是它的屬性。

方法:方法就是類的功能,也就是定義在類裏面的函數,它實現了某個功能,好比說人有睡覺的功能。

構造函數:什麼是構造函數,就是類在實例化的時候作的某些初始化操做,好比說人,你造一個汽車的時候,它得有顏色、型號等等。

析構函數:析構函數就是這個實例在銷燬的時候作的一些操做。

一、定義類:

定義類使用class關鍵字,類名通常咱們開發的時候首字母要大寫

Python中有兩種類,經典類和新式類

經典類和新型類在寫的方面的區別就是經典類沒有集成object的父類,新式類繼承了object。

Python3.x中,類繼承或不繼承object類,經典類和新型類的沒有區別,默認都繼承object

Python2.x和Python3.x新型類和經典類區別是,在多繼承時Python3.x是廣度優先,Python2.x是深度優先。

# class Person(object):#這是經典類
class Person:#類,類名都以大寫字母開頭(這是新式類)
    country = 'China' #類變量
    eyes = 2
    ears = 2
    mouth = 1
    def __init__(self,name):#構造函數:函數就是這個類在初始化的時候執行的
        self.name = name #綁定屬性
        #實例變量,成員變量
    def __del__(self): #析構函數,這個實例被銷燬的時候自動執行的
        print("這是析構函數")
    def cry(self): # 方法
        print('%s 哇哇哇'%self.name)

print(Person.country) # 獲取類屬性 類名.類屬性名

haha = Person('哈哈')#實例化,由於在上面的構造函數裏面指定了必須傳name,因此在實例化的時候要把name傳進去
haha.cry() #調用實例方法

執行結果以下:

二、繼承

class F: # 這是父類
    def __init__(self, name, sex):
        self.name = name
        self.sex = sex

    def info(self):  # 方法
        print('name is %s sex is %s ' % (self.name, self.sex))

class S(F):  # 子類,繼承F這個類
    pass

s1 = S('牛牛', '')  # 實例化子類
s1.info()  # 由於繼承父類,因此父類的方法他都有

若是在父類裏面有一個方法,子類裏面也有同名方法,可是子類想重寫一下父類的方法增長新功能。這麼寫:

# 繼承構造函數,新式類經過super來繼承,經典類經過父類類名來繼承。就能夠在繼承基類原有的屬性的同時,爲本類添加特有的屬性
class Animal(): # 父類
    def __init__(self, name,age):
        self.name = name
        self.age = age
    def eat(self):
        print('%s在吃東西'%self.name)

class Bird(Animal): # 子類
    def __init__(self, name, age,color): #子類增長顏色屬性
        # Animal.__init__(self,name,age) #修改父類的方法,這是經典類裏面的寫法
        super(Bird, self).__init__(name,age)  # 修改父類方法,這是新式類裏面的寫法
        # 注:init中爲基類中所含有的全部屬性
        self.color = color

    def demo(self):
        print('%s的顏色是%s'%(self.name,self.color))

obj = Bird('啄木鳥',1,'red') #實例化子類
obj.eat()
obj.demo()

多繼承:

上面寫的都是單繼承的,python裏面還支持多繼承,多繼承就是繼承多個父類。

python3中多繼承都是廣度優先的,在python2中有點不一樣,經典類是深度優先,新式類是廣度優先。

class A:
    def say(self):
        print('A')
class B(A):
    def say(self):
        print('B')
class C(A):
    pass
class D(C, B):
    pass

s = D()
s.say()

三、多態

多態:python裏面是不直接支持多態的,能夠經過別的方法來實現多態

經過下面的例子就能夠實現一種接口,多種實現

對於下面的cry方法來講,無論你傳入的是什麼對象,只要有cry的方法,都會去調用它的cry方法,不用再一個個的去調用了。

# 多態
class Animal(object): # 父類
    def __init__(self, name):
        self.name = name

class Dog(Animal): # 狗類,有叫的方法
    def cry(self):
        print('狗 [%s] 汪汪汪' % self.name)

class Cat(Animal): # 貓類,有叫的方法
    def cry(self):
        print('貓 [%s] 喵喵喵' % self.name)

def cry(obj): #定義一個函數,去調用傳進來的實例的cry方法
    obj.cry()

d1 = Dog('大黃')  # 實例化狗
d2 = Dog('小黃')  # 實例化狗
c1 = Cat('小白')  # 實例化貓
c2 = Cat('小黑')  # 實例化貓
cry(d1)  # 把對象d1傳進來
cry(d2)  # 把對象d2傳進來
objs = [d1, d2, c1, c2]  # 把上面實例化的對象都放到一個list裏面
for obj in objs:  # 循環統一調用
    cry(obj)

四、私有方法、私有屬性

私有就是隻有在類裏面能夠訪問,實例化以後不能夠訪問和調用,有私有方法和私有屬性。

私有就把變量名或者函數名前面加上"__"兩個下劃線,其實就是經過私有來實現封裝的。

class Dog:
    __type = '' #私有屬性
    def cry(self):
        self.__test() #調用私有方法
        print('私有屬性%s'%self.__type)
        print('狗[%s]汪汪汪'%self.name)
    def __test(self):#私有方法
        self.name = 'test'

d = Dog()
d.cry()  #能夠正常調用
d.__type() #報錯,由於是私有屬性,在外面不能訪問
d.__test() #報錯,由於是私有方法,在外面不能訪問

五、靜態方法、類方法

類方法:就是被classmethod()函數處理過的函數,可以直接經過類名和實例化對象進行調用(注:類方法中不能使用對象屬性)

靜態方法:靜態方法至關於類層面的全局函數,能夠經過類名和實例化對象調用。經過staticmethod()定義靜態方法,靜態方法沒有self參數。(注:靜態方法若是使用類屬性,則經過類名調用)

class Stu(object):
    country = 'china'  # 類變量,類變量

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

    @staticmethod
    # 靜態方法,不接受self。和類自己沒有什麼關係了,就至關於在類裏面定義了一個方法而已
    def say():
        print('xxx')
        print(Stu.country) #調用類變量直接經過類名訪問

    @classmethod
    # 類方法,和靜態方法不一樣的是,它可使用類變量,必需要傳一個值,表明的就是這個類
    def hello(cls):
        print(cls.country)

    def hi(self):
        # 這個是實例方法
        print(self.name)

t = Stu('name')
Stu.hello() #經過類名直接調用
Stu.say()
t.hi()
t.say()
t.hello()

6、Python的垃圾回收機制

Python採用垃圾回收機制來清理再也不使用的對象,Python中提供了gc模塊來釋放再也不使用的對象。

python採用「引用計數」的方式來處理回收,也就是說當某個對象在其做用域內不再被其它對象引用的時候,Python就自動清除對象。

Python中也提供了collect()函數,來一次性收集全部待處理的對象,並返回待處理對象的數目(gc.collect())

相關文章
相關標籤/搜索