python開發第六篇--遞歸函數和麪對對象編程初識

遞歸函數

遞歸函數的用法:

- 遞歸函數:在一個函數裏在調用這個函數自己。
- 遞歸的最大深度:998

實例

找一個函數的索引位置,遞歸實現python

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
def two_serarch(list,aim,start=0,end=None):
    end=len(list) -1 if end is None else end
    if end >= start:
        mid_index = (end - start) // 2 + start
        if aim > list[mid_index]:
            return two_serarch(list,aim,start=mid_index+1,end=end)
        elif aim < list[mid_index]:
            return two_serarch(list,aim,start=start,end=mid_index-1)
        elif aim == list[mid_index]:
            return mid_index
        else:
            return "沒有此值"
    else:
        return "沒有此值"

循環一個列表裏的元素,遇到列表在循環git

def each_list(list_name):
    for i in list_name:
        if isinstance(i,list):
            each_list(i)
        else:
            print (i)

面向對象編程

初識面對對象

面向過程的程序設計的核心是過程(流水線式思惟),過程即解決問題的步驟,面向過程的設計就比如精心設計好一條流水線,考慮周全何時處理什麼東西。編程

- 優勢是:極大的下降了寫程序的複雜度,只須要順着要執行的步驟,堆疊代碼便可。
- 缺點是:一套流水線或者流程就是用來解決一個問題,代碼牽一髮而動全身。
- 應用場景:一旦完成基本不多改變的場景,著名的例子有Linux內核,git,以及Apache HTTP Server等。

面向對象的程序設計的核心是對象(上帝式思惟),要理解對象爲什麼物,必須把本身當成上帝,上帝眼裏世間存在的萬物皆爲對象,不存在的也能夠創造出來。面向對象的程序設計比如如來設計西遊記,如來要解決的問題是把經書傳給東土大唐,如來想了想解決這個問題須要四我的:唐僧,沙和尚,豬八戒,孫悟空,每一個人都有各自的特徵和技能(這就是對象的概念,特徵和技能分別對應對象的屬性和方法),然而這並很差玩,因而如來又安排了一羣妖魔鬼怪,爲了防止師徒四人在取經路上被搞死,又安排了一羣神仙保駕護航,這些都是對象。而後取經開始,師徒四人與妖魔鬼怪神仙互相纏鬥着直到最後取得真經。如來根本不會管師徒四人按照什麼流程去取。面向對象的程序:函數

- 優勢是:解決了程序的擴展性。對某一個對象單獨修改,會馬上反映到整個體系中,如對遊戲中一我的物參數的特徵和技能修改都很容易。
- 缺點:可控性差,沒法向面向過程的程序設計流水線式的能夠很精準的預測問題的處理流程與結果,面向對象的程序一旦開始就由對象之間的交互解決問題,即使是上帝也沒法預測最終結果。因而咱們常常看到一個遊戲人某一參數的修改極有可能致使陰霸的技能出現,一刀砍死3我的,這個遊戲就失去平衡。
- 應用場景:需求常常變化的軟件,通常需求的變化都集中在用戶層,互聯網應用,企業內部軟件,遊戲等都是面向對象的程序設計大顯身手的好地方。

名詞:類、對象、實例、實例化設計

類的相關知識

1.聲明code

def functionName(args):
     '函數文檔字符串'
      函數體 
'''
class 類名:
    '類的文檔字符串'
    類體
'''
#咱們建立一個類
class Data:
    pass

2.屬性orm

class Person:   #定義一我的類
    role = 'person'  #人的角色屬性都是人
    def walk(self):  #人均可以走路,也就是有一個走路方法
        print("person is walking...")
print(Person.role)  #查看人的role屬性
print(Person.walk)  #引用人的走路方法,注意,這裏不是在調用

3.實例化:類名加括號就是實例化,會自動觸發__init__函數的運行,能夠用它來爲每一個實例定製本身的特徵對象

class Person:   #定義一我的類
    role = 'person'  #人的角色屬性都是人
    def __init__(self,name):
        self.name = name  # 每個角色都有本身的暱稱;
        
    def walk(self):  #人均可以走路,也就是有一個走路方法
        print("person is walking...")


print(Person.role)  #查看人的role屬性
print(Person.walk)  #引用人的走路方法,注意,這裏不是在調用

4.實例化的過程就是類——>對象的過程繼承

- 語法:對象名 = 類名(參數)
    1.建立一個對象,開闢一個空間
    2.自動執行__init__方法,而且對象自己傳給self
    3.將傳進的內容封裝給對象自己

5.類屬性的補充遞歸

一:咱們定義的類的屬性到底存到哪裏了?有兩種方式查看
dir(類名):查出的是一個名字列表
類名.__dict__:查出的是一個字典,key爲屬性名,value爲屬性值

二:特殊的類屬性
類名.__name__# 類的名字(字符串)
類名.__doc__# 類的文檔字符串
類名.__base__# 類的第一個父類
類名.__bases__# 類全部父類構成的元組
類名.__dict__# 類的字典屬性
類名.__module__# 類定義所在的模塊
類名.__class__# 實例對應的類(僅新式類中)

對象的相關知識

class 類名:
    def __init__(self,參數1,參數2):
        self.對象的屬性1 = 參數1
        self.對象的屬性2 = 參數2
    def 方法名(self):pass
    def 方法名2(self):pass

對象名 = 類名(1,2)  #對象就是實例,表明一個具體的東西
                  #類名() : 類名+括號就是實例化一個類,至關於調用了__init__方法
                  #括號裏傳參數,參數不須要傳self,其餘與init中的形參一一對應
                  #結果返回一個對象
對象名.對象的屬性1   #查看對象的屬性,直接用 對象名.屬性名 便可
對象名.方法名()     #調用類中的方法,直接用 對象名.方法名() 便可

練習:

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

小明,10歲,男,上山去砍柴
小明,10歲,男,開車去東北
小明,10歲,男,最愛大保健
老李,90歲,男,上山去砍柴
老李,90歲,男,開車去東北
老李,90歲,男,最愛大保健
class Output:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def chopp_wood(self):
        print("{name},{age}歲,{sex},上山去砍柴".format(name=self.name,age=self.age,sex=self.sex))
    def drive_car(self):
        print("{name},{age}歲,{sex},開車去東北".format(name=self.name,age=self.age,sex=self.sex))
    def health_care(self):
        print("{name},{age}歲,{sex},最愛大保健".format(name=self.name,age=self.age,sex=self.sex))
xiaoming = Output("小明",10,"男")  #實例化兩個對象
laoli = Output("老李",90,"男")
xiaoming.chopp_wood()  
xiaoming.drive_car()
xiaoming.health_care()
laoli.chopp_wood()
laoli.drive_car()
laoli.health_care()

類名稱空間與對象的名稱空間

1.建立一個類就會建立一個類的名稱空間,用來存儲類中定義的全部名字,這些名字稱爲類的屬性

- 類有兩種屬性:靜態屬性和動態屬性
    1.靜態屬性就是直接在類中定義的變量
    2.動態屬性就是定義在類中的方法
- 其中類的數據屬性是共享給全部對象的
- 而類的動態屬性是綁定到全部對象的

2.建立一個對象/實例就會建立一個對象/實例的名稱空間,存放對象/實例的名字,稱爲對象/實例的屬性
在obj.name會先從obj本身的名稱空間裏找name,找不到則去類中找,類也找不到就找父類...最後都找不到就拋出異常

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

1.繼承

- 繼承是一種建立新類的方式,在python中,新建的類能夠繼承一個或多個父類,父類又可稱爲基類或超類,新建的類稱爲派生類或子類。

python中類的繼承分爲:單繼承和多繼承

class ParentClass1: #定義父類
    pass

class ParentClass2: #定義父類
    pass

class SubClass1(ParentClass1): #單繼承,基類是ParentClass1,派生類是SubClass
    pass

class SubClass2(ParentClass1,ParentClass2): #python支持多繼承,用逗號分隔開多個繼承的類
    pass

查看繼承:

print(SubClass1.__bases__)#__base__只查看從左到右繼承的第一個子類,__bases__則是查看全部繼承的父類
print(SubClass2.__bases__)

若是沒有指定基類,python的類會默認繼承object類

print(ParentClass1.__bases__)
print(ParentClass2.__bases__)
(<class 'object'>,)
(<class 'object'>,)

2.繼承的重要性

- 繼承來重用代碼
==========================第一部分
例如

  貓能夠:爬樹、吃、喝、拉、撒

  狗能夠:看門、吃、喝、拉、撒

若是咱們要分別爲貓和狗建立一個類,那麼就須要爲 貓 和 狗 實現他們全部的功能,僞代碼以下:
 

#貓和狗有大量相同的內容
class 貓:

    def爬樹(self):
        print '爬樹'

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 拉(self):
        # do something

    def 撒(self):
        # do something

class 狗:

    def 看門(self):
        print '看門'

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 拉(self):
        # do something

    def 撒(self):
        # do something



==========================第二部分
上述代碼不難看出,吃、喝、拉、撒是貓和狗都具備的功能,而咱們卻分別的貓和狗的類中編寫了兩次。若是使用 繼承 的思想,以下實現:

  動物:吃、喝、拉、撒

     貓:爬樹(貓繼承動物的功能)

     狗:看門(狗繼承動物的功能)

僞代碼以下:
class 動物:

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 拉(self):
        # do something

    def 撒(self):
        # do something

# 在類後面括號中寫入另一個類名,表示當前類繼承另一個類
class 貓(動物):

    def爬樹(self):
        print '爬樹'

# 在類後面括號中寫入另一個類名,表示當前類繼承另一個類
class 狗(動物):

     def 看門(self):
        print '看門'




==========================第三部分
#繼承的代碼實現
class Animal:

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

    def drink(self):
        print ("%s 喝 " %self.name)

    def shit(self):
        print ("%s 拉 " %self.name)

    def pee(self):
        print ("%s 撒 " %self.name)


class Cat(Animal):

    def __init__(self, name):
        self.name = name
        self.breed = '貓'

    def爬樹(self):
        print '爬樹'

class Dog(Animal):

    def __init__(self, name):
        self.name = name
        self.breed='狗'
  
    def 看門(self):
        print '看門'



# ######### 執行 #########
代碼以下:

class Animal:

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

    def drink(self):
        print("%s 喝 " % self.name)

    def shit(self):
        print("%s 拉 " % self.name)

    def pee(self):
        print("%s 撒 " % self.name)


class Cat(Animal):

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

    def up_tree(self):
        print("爬樹")


class Dog(Animal):

    def __init__(self, name):
        self.name = name
        self.breed = '狗'

    def look_door(self):
        print("看門")

mao = Cat("二虎")
mao.eat()
mao.drink()
mao.shit()
mao.pee()
mao.up_tree()

3.Python的類繼承了多個類,那麼其尋找方法的方式有兩種,分別是:深度優先和廣度優先

- 當類是經典類時,多繼承狀況下,會按照深度優先方式查找。
- 當類是新式類時,多繼承狀況下,會按照廣度優先方式查找。
- 經典類和新式類,從字面上能夠看出一個老一個新,新的必然包含了跟多的功能,也是以後推薦的寫法,從寫法上區分的話,若是 當前類或者父類繼承了object類,那麼該類即是新式類,不然即是經典類。
- python2默認是經典類
- python3默認是新式類

經典類繼承:

class D:
    def bar(self):
        print 'D.bar'
class C(D):
    def bar(self):
        print 'C.bar'
class B(D):
    def bar(self):
        print 'B.bar'
class A(B, C):
    def bar(self):
        print 'A.bar'
a = A()
# 執行bar方法時
# 首先去A類中查找,若是A類中沒有,則繼續去B類中找,若是B類中麼有,則繼續去D類中找,若是D類中麼有,則繼續去C類中找,若是仍是未找到,則報錯
# 因此,查找順序:A --> B --> D --> C
# 在上述查找bar方法的過程當中,一旦找到,則尋找過程當即中斷,便不會再繼續找了
a.bar()
經典類多繼承

新式類繼承:

class D(object):
    def bar(self):
        print 'D.bar'
class C(D):
    def bar(self):
        print 'C.bar'
class B(D):
    def bar(self):
        print 'B.bar'
class A(B, C):
    def bar(self):
        print 'A.bar'
a = A()
# 執行bar方法時
# 首先去A類中查找,若是A類中沒有,則繼續去B類中找,若是B類中麼有,則繼續去C類中找,若是C類中麼有,則繼續去D類中找,若是仍是未找到,則報錯
# 因此,查找順序:A --> B --> C --> D
# 在上述查找bar方法的過程當中,一旦找到,則尋找過程當即中斷,便不會再繼續找了
a.bar()
新式類多繼承

經典類:首先去A類中查找,若是A類中沒有,則繼續去B類中找,若是B類中麼有,則繼續去D類中找,若是D類中麼有,則繼續去C類中找,若是仍是未找到,則報錯
新式類:首先去A類中查找,若是A類中沒有,則繼續去B類中找,若是B類中麼有,則繼續去C類中找,若是C類中麼有,則繼續去D類中找,若是仍是未找到,則報錯
注意:在上述查找過程當中,一旦找到,則尋找過程當即中斷,便不會再繼續找了
4.組合
組合指的是,在一個類中以另一個類的對象做爲數據屬性,稱爲類的組合
文字遊戲:

class Game_person:
    def __init__(self,nickname,sex,hp,ad):
        self.nickname = nickname
        self.sex = sex
        self.hp = hp
        self.ad = ad
    def attack(self,p):
        p.hp = p.hp - self.ad   #剩餘血量
        print('%s攻擊了%s,%s還剩%s血量'%(self.nickname,p.nickname,p.nickname,p.hp))
    def wuqi(self,wuqi):
        self.wuqi = wuqi   #tian.wuqi(wuqi1)武器類的對象封裝到人的對象中當作一個屬性.就叫作組合.
class Weapon:
    def __init__(self,name,ad):  #武器的名字,武器的傷害
        self.name =name
        self.ad =ad
    def fight(self,p1,p2):
        p2.hp = p2.hp - self.ad
        print('%s使用%s打了%s%s血,%s還剩%s滴血'%(p1.nickname,self.name ,p2.nickname,self.ad,p2.nickname,p2.hp))

tian = Game_person("TIAN","男",200,10)
didi = Game_person("DIDI","女",200,50)
wuqi = Weapon("鞭子",50)
tian.wuqi(wuqi)
tian.wuqi.fight(tian,didi)
相關文章
相關標籤/搜索