Python開發【第六章】:面向對象

編程範式

  編程是程序員用特定的語法+數據結構+算法組成的代碼來告訴計算機如何執行任務的過程,一個程序是程序員爲了獲得一個任務結果而編寫的一組指令的集合,正所謂條條大路通羅馬,實現一個任務的方式有不少種不一樣的方式, 對這些不一樣的編程方式的特色進行概括總結得出來的編程方式類別,即爲編程範式。 不一樣的編程範式本質上表明對各類類型的任務採起的不一樣的解決問題的思路, 大多數語言只支持一種編程範式,固然也有些語言能夠同時支持多種編程範式。 兩種最重要的編程範式分別是面向過程編程和麪向對象編程html

 

面向過程編程

  面向過程編程最易被初學者接受,其每每用一長段代碼來實現指定功能,開發過程當中最多見的操做就是粘貼複製,即:將以前實現的代碼塊複製到現需功能處。程序從上到下一步步執行,一步步從上到下,從頭至尾的解決問題 。基本設計思路就是程序一開始是要着手解決一個大的問題,而後把一個大問題分解成不少個小問題或子過程,這些子過程再執行的過程再繼續分解直到小問題足夠簡單到能夠在一個小步驟範圍內解決。這樣作的問題也是顯而易見的,就是若是你要對程序進行修改,對你修改的那部分有依賴的各個部分你都也要跟着修改, 隨着程序愈來愈大, 這種編程方式的維護難度會愈來愈高。 因此咱們通常認爲, 若是你只是寫一些簡單的腳本,去作一些一次性任務,用面向過程的方式是極好的,但若是你要處理的任務是複雜的,且須要不斷迭代和維護的, 那仍是用面向對象最方便了。python

示例:程序員

#面向過程編程

while True:
    if cpu利用率 > 90%:
        #發送郵件提醒
        鏈接郵箱服務器
        發送郵件
        關閉鏈接
 
    if 硬盤使用空間 > 90%:
        #發送郵件提醒
        鏈接郵箱服務器
        發送郵件
        關閉鏈接
 
    if 內存佔用 > 80%:
        #發送郵件提醒
        鏈接郵箱服務器
        發送郵件
        關閉鏈接

 

函數式編程

  將某功能代碼封裝到函數中,往後便無需重複編寫,僅調用函數便可算法

示例:編程

練習:在終端輸出以下信息

小明,10歲,男,上山去砍柴
小明,10歲,男,開車去東北
小明,10歲,男,最愛大保健
老李,90歲,男,上山去砍柴
老李,90歲,男,開車去東北
老李,90歲,男,最愛大保健
練習一
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#-Author-Lian

#函數式編程

def firewood(name, age, gender):
    print("%s,%s歲,%s,上山去砍柴" %(name, age, gender))

def drive(name, age, gender):
    print("%s,%s歲,%s,開車去東北" %(name, age, gender))

def dbj(name, age, gender):
    print("%s,%s歲,%s,最愛大保健" %(name, age, gender))


firewood('小明', 10, '男')
drive('小明', 10, '男')
dbj('小明', 10, '男')
#小明,10歲,男,上山去砍柴
#小明,10歲,男,開車去東北
#小明,10歲,男,最愛大保健

firewood('老李', 90, '男')
drive('老李', 90, '男')
dbj('老李', 90, '男')
#老李,90歲,男,上山去砍柴
#老李,90歲,男,開車去東北
#老李,90歲,男,最愛大保健

 

面向對象編程

一、類、對象、實例服務器

  OOP編程是利用「類」和「對象」來建立各類模型來實現對真實世界的描述,使用面向對象編程的緣由一方面是由於它可使程序的維護和擴展變得更簡單,而且能夠大大提升程序開發效率 ,另外,基於面向對象的程序可使它人更加容易理解你的代碼邏輯,從而使團隊開發變得更從容。數據結構

示例:app

練習:在終端輸出以下信息

小明,10歲,男,上山去砍柴
小明,10歲,男,開車去東北
小明,10歲,男,最愛大保健
老李,90歲,男,上山去砍柴
老李,90歲,男,開車去東北
老李,90歲,男,最愛大保健
練習一
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#-Author-Lian

#面向對象
class Foo:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def firewood(self):
        print("%s,%s歲,%s,上山去砍柴" % (self.name, self.age, self.gender))

    def drive(self):
        print("%s,%s歲,%s,開車去東北" % (self.name, self.age, self.gender))

    def dbj(self):
        print("%s,%s歲,%s,最愛大保健" % (self.name, self.age, self.gender))

xiaoming = Foo('小明', 10, '男')
xiaoming.firewood()
xiaoming.drive()
xiaoming.dbj()
#小明,10歲,男,上山去砍柴
#小明,10歲,男,開車去東北
#小明,10歲,男,最愛大保健

laoli = Foo('老李', 90, '男')
laoli.firewood()
laoli.drive()
laoli.dbj()
#老李,90歲,男,上山去砍柴
#老李,90歲,男,開車去東北
#老李,90歲,男,最愛大保健

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

上面的程序作個簡單認識便可,下面咱們經過寫一個cs程序來對面向對象編程作進一步認識模塊化

CS遊戲
1、暫不考慮開發場地等複雜的東西,角色恐怖份子、警察
2、每一個人都有生命值
3、武器
4、被打中後就會掉血的功能
5、開槍功能
6、換子彈
七、買槍
CS遊戲
#!/usr/bin/env python
# -*- coding:utf-8 -*-
#-Author-Lian

#面向對象class
class Role(object):      #定義一個類, class是定義類的語法,Role是類名,(object)是新式類的寫法,暫且先記住
    def __init__(self,name,role,weapon,life_value=100,money=15000):#初始化函數,在生成一個角色時要初始化的一些屬性就填寫在這裏
        self.name = name        #__init__中的第一個參數self爲實例名稱
        self.role = role      
        self.weapon = weapon
        self.life_value = life_value
        self.money = money
        #__init__()叫作初始化方法(或構造方法), 在類被調用時,這個方法(雖然它是函數形式,但在類中就不叫函數了, 叫方法)會自動執行,
                                                                                                # 進行一些初始化的動做
    def shot(self):
        # 開了槍後要減子彈數
        print("%s is shooting......."%(self.name))

    def got_shot(self):
        # 中槍後要減血
        print("ah.....%s:I got shot...."%(self.name))

    def buy_gun(self,gun_name):
        # 檢查錢夠不夠,買了槍後要扣錢
        print("%s just bought %s "%(self.name,gun_name))

#生成一個角色 , 會自動把參數傳給Role下面的__init__(...)方法,這個過程叫作類的實例化,r1叫作類的實例
r1 = Role('Alex','police',"AK47")   #此時self 至關於 r1 ,  Role(r1,'Alex','police','AK47’)
r2 = Role('Jack','terrorist',"B22") #此時self 至關於 r2 ,  Role(r2,'Jack','terrorist','B22’)

print(r1,type(r1))
print(r1.role)
r1.shot()
r1.got_shot()
r1.buy_gun("DZT100")
# <__main__.Role object at 0x005A5BF0> <class '__main__.Role'>
# police
# Alex is shooting.......
# ah.....Alex:I got shot....
# Alex just bought DZT100

 

二、類變量和實例變量 

類變量爲你們都共有的變量,只加載在類內存當中,不會加載在每一個實例裏;舉個栗子:建立14億用戶,你們國籍都是中國,若是不把國籍寫到類變量中,而是寫到實例變量默認參數中,則14億個實例,每一個都要加載國籍到內存當中,會佔用大量內存,這就是爲何咱們要了解類變量的意義

#類變量和實例變量
class Role(object):      #定義一個類, class是定義類的語法
    n = 123              #類變量
    name = "類name"
    def __init__(self,name,role,weapon,life_value=100,money=15000):
        self.name = name        #實例變量
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money

r1 = Role('Alex','police',"AK47")   #實例

print(Role.n,r1.n)
print(Role.name,r1.name)
#123 123
#類name Alex

由上面程序可知,類變量對全局生效,輸入類名可直接調用;當類變量與實例變量相同且同時存在的話,實例變量優先

#實例變量
class Role(object):      #定義一個類, class是定義類的語法
    n = 123              #類變量
    name = "類name"
    def __init__(self,name,role,weapon,life_value=100,money=15000):
        self.name = name        #實例變量
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money

r1 = Role('Alex','police',"AK47")   #實例
r1.name="wupeiqi"
r1.bullet= True

print(r1.name,r1.bullet)
#wupeiqi True

類進行實例化以後,還能夠對實例變量從新賦值、增長變量 

#類變量和實例變量
class Role(object):      #定義一個類, class是定義類的語法
    n = 123              #類變量
    name = "類name"
    def __init__(self,name,role,weapon,life_value=100,money=15000):
        self.name = name        #實例變量
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money

r1 = Role('Alex','police',"AK47")   #實例
r2 = Role('lzl','terrorist','B22')

r1.n = "r1的123"
print(r1.name,r1.n)
print(r2.name,r2.n)
# Alex r1的123
# lzl 123

Role.n = "Role的123"
print(r1.name,r1.n)
print(r2.name,r2.n)
# Alex r1的123
# lzl Role的123

執行上面的程序發現,賦值r1.n後只是影響到實例r1,對r2.n並無任何影響,這是由於賦值的實例變量與類變量名同樣時,並不會改變類變量中的值,隻影響到當前實例;當從新賦值類變量時,r2也跟着改變;哈哈,此時你覺得你都懂了,那讓咱們對上面的程序作個升級吧!!

#類變量和實例變量
class Role(object):      #定義一個類, class是定義類的語法
    list = []      #定義一個列表類變量

    def __init__(self,name,role,weapon,life_value=100,money=15000):
        self.name = name        #實例變量
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money

r1 = Role('Alex','police',"AK47")   #實例
r2 = Role('lzl','terrorist','B22')

print(Role.list)            #此時list爲空
#[]

r1.list.append("from r1")
r2.list.append("from r2")

print(r1.list)
print(r2.list)
#['from r1', 'from r2']
# ['from r1', 'from r2']

print(Role.list)
# ['from r1', 'from r2']

從上面的程序可看出r一、r2改變了類變量;懶得解釋了,本身理解吧O(∩_∩)O哈哈~

 

三、析構函數 

在實例釋放、銷燬的時候執行,一般用於作一下收尾工做(如關閉數據鏈接)

#析構函數
class Role(object):      #定義一個類, class是定義類的語法
    def __init__(self,name,role,weapon,life_value=100,money=15000):
        self.name = name        #實例變量
        self.role = role
        self.weapon = weapon
        self.life_value = life_value
        self.money = money

    def __del__(self):
        print("%s 完全死了"%self.name)

    def shot(self):
        # 開了槍後要減子彈數
        print("%s is shooting......."%(self.name))

    def got_shot(self):
        # 中槍後要減血
        print("ah.....%s:I got shot...."%(self.name))

r1 = Role('Alex','police',"AK47")
r2 = Role('Wupeiqi','terrorist','B22')

r1.got_shot()
del r1

r2.got_shot()

# ah.....Alex:I got shot....
# Alex 完全死了
# ah.....Wupeiqi:I got shot....
# Wupeiqi 完全死了

程序結束、del刪除實例時纔會執行__del__裏的內容

 

四、私有屬性、私有方法

記住私有的概念:只能在類裏面進行調用 看完下面的代碼你就明白了

#class私有屬性、私有方法
class Role(object):      #定義一個類, class是定義類的語法
    def __init__(self,name,role,weapon,life_value=100,money=15000):
        self.name = name
        self.role = role
        self.weapon = weapon
        self.__life_value = life_value      #定義私有屬性,私有屬性在外部不能調用,只能在類裏面使用
        self.money = money

    def show_status(self):                  #定義函數,調用私有屬性
        print("name:%s weapon:%s life_value:%s"%(self.name,self.weapon,self.__life_value))

    def __shot(self):                      #定義私有方法
        print("%s is shooting......."%(self.name))

    def got_shot(self):
        self.__shot()                       #調用私有方法
        print("ah.....%s:I got shot...."%(self.name))

r1 = Role('lzl','police',"AK47")

#私有屬性
#print(r1.__life_value)          #外部調用life_vaule 直接報錯
#AttributeError: 'Role' object has no attribute '__life_value'
r1.show_status()                #經過方法執行私有屬性
#name:lzl weapon:AK47 life_value:100

#私有方法
#r1.__shot()                     #外部調用私有方法 直接報錯
#AttributeError: 'Role' object has no attribute '__shot'
r1.got_shot()                    #經過其餘方法執行私有方法
# lzl is shooting.......
# ah.....lzl:I got shot....

 

五、繼承

繼承:它可使用現有類的全部功能,並在無需從新編寫原來的類的狀況下對這些功能進行擴展

#類的繼承

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

    def eat(self):
        print("%s is eating..."%self.name)

    def sleep(self):
        print("%s is sleeping...."%self.name)

class Man(People):      #繼承類People
    def play(self):         #增長新功能
        print("%s is playing...."%self.name)

    def sleep(self):        #重構sleep功能
        People.sleep(self)
        print("man is sleeping....")

class Woman(People):         #繼承類People
    def get_birth(self):        #增長新功能
        print("%s is born a boby...."%self.name)

m1 = Man("lianzhilie",22)
w1 = Woman("Alex",33)

m1.eat()                #調用People方法
m1.play()               #調用Man方法
# lianzhilie is eating...
# lianzhilie is playing....

m1.sleep()
# lianzhilie is sleeping....
# man is sleeping...

w1.get_birth()
# Alex is born a boby...

由上面程序可知,類的繼承可省大量重複的代碼

#類的繼承,子類初始化

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

    def eat(self):
        print("%s is eating..."%self.name)

    def sleep(self):
        print("%s is sleeping...."%self.name)

class Man(People):
    def __init__(self,name,age,money):     #重構初始化 覆蓋父類
        # People.__init__(self,name,age)      #加載父類初始化
        super(Man,self).__init__(name,age)       #加載父類初始化
        self.money = money
        print("%s 一出生就有 $%s"%(self.name,self.money))

    def play(self):         #增長新功能
        print("%s is playing...."%self.name)

class Woman(People):
    def get_birth(self):
        print("%s is born a boby...."%self.name)

m1 = Man("lianzhilie",22,1000)
w1 = Woman("Alex",33)
#lianzhilie 一出生就有 $1000

子類須要重構初始化時,會把父類的初始化覆蓋掉,因此在重構時須要加載父類初始化

# 類的繼承-多繼承

class People(object):       #新式類
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self):
        print("%s is eating..." % self.name)

    def sleep(self):
        print("%s is sleeping...." % self.name)

class Relation(object):
    def make_friends(self,obj):
        print("%s is making friends with %s"%(self.name,obj.name))

class Man(Relation,People):             #多繼承
    def play(self):
        print("%s is playing...." % self.name)

class Woman(People):
    def get_birth(self):
        print("%s is born a boby...." % self.name)

m1 = Man("lianzhilie", 22)
w1 = Woman("Alex", 33)

m1.make_friends(w1)
#lianzhilie is making friends with Alex

多繼承時需注意,在多繼承中從父類繼承初始化屬性時,順序從左到右開始初始化,只要初始化到屬性數據就再也不向後繼續,因此越往前越優先;當父類有初始化,子類也有初始化時,執行子類的初始化,父類的不生效

剛纔咱們已經知道了新式類的概念,那麼經典類與新式類的區別是什麼呢?!

經過上面的程序咱們知道Python的類能夠繼承多個類,那若是Python的類若是繼承了多個類,有多層繼承關係,那麼其初始化時尋找的路線是什麼樣的呢?,經過下面這段代碼來看下:Python3之後都是新式類了

#經典類

class A():
    def __init__(self):
        print("A")
class B(A):
    pass

class C(A):
    def __init__(self):
        print("C")

class D(B,C):
    pass

obj = D()
#A


#新式類

class A(object):
    def __init__(self):
        print("A")

class B(A):
    pass

class C(A):
    def __init__(self):
        print("C")

class D(B,C):
    pass

obj = D()
#C

 當類是經典類時,多繼承狀況下,會按照深度優先方式查找;當類是新式類時,多繼承狀況下,會按照廣度優先方式查找;具體參考下圖

 

六、多態

  多態性(polymorphisn)是容許你將父對象設置成爲和一個或更多的他的子對象相等的技術,賦值以後,父對象就能夠根據當前賦值給它的子對象的特性以不一樣的方式運做。簡單的說,就是一句話:容許將子類類型的指針賦值給父類類型的指針。那麼,多態的做用是什麼呢?咱們知道,封裝能夠隱藏實現細節,使得代碼模塊化;繼承能夠擴展已存在的代碼模塊(類);它們的目的都是爲了——代碼重用。而多態則是爲了實現另外一個目的——接口重用!多態的做用,就是爲了類在繼承和派生的時候,保證使用「家譜」中任一類的實例的某一屬性時的正確調用。Pyhon不直接支持多態,但能夠間接實現

看完上面的話,徹底懵逼; 說人話!!--》一個接口,多種實現,實現接口重用 

#多態
class Animal:
    def __init__(self, name):  # Constructor of the class
        self.name = name

    @staticmethod
    def animal_talk(obj):
        obj.talk()

class Cat(Animal):
    def talk(self):
        print('%s:Meow!'%(self.name))

class Dog(Animal):
    def talk(self):
        print('%s:Woof! Woof!'%(self.name))

c = Cat('Missy')
d = Dog('Lassie')

Animal.animal_talk(c)
Animal.animal_talk(d)

# Missy:Meow!
# Lassie:Woof! Woof!

  

 

 

 

  

 

轉載於:https://www.cnblogs.com/lianzhilei/p/5813986.html