python面向對象詳解,人生苦短,我用python-- Day6 面向對象

 2023-11-07 阅读 26 评论 0

摘要:目錄大綱                         1.面向對象編程介紹 2.為什么要用面向對象進行開發? 3.面向對象的特性:封裝、繼承、多態 4.類、方法 面向過程 VS 面向對象?                            編程范式 編程是

目錄大綱                        

1.面向對象編程介紹
2.為什么要用面向對象進行開發?
3.面向對象的特性:封裝、繼承、多態
4.類、方法

面向過程 VS 面向對象?                           

編程范式

編程是 程序員用特定的語法+數據結構+算法組成的代碼來告訴計算機如何執行任務的過程 ,一個程序是程序員為了得到一個任務結果而編寫的一組指令的集合,正所謂條條大路通羅馬,實現一個任務的方式有很多種不同的方式, 對這些不同的編程方式的特點進行歸納總結得出來的編程方式類別,即為編程范式。 不同的編程范式本質上代表對各種類型的任務采取的不同的解決問題的思路, 大多數語言只支持一種編程范式,當然也有些語言可以同時支持多種編程范式。 兩種最重要的編程范式分別是面向過程編程面向對象編程。?---引用大王博客。http://www.cnblogs.com/alex3714/articles/5188179.html

面向過程編程(Procedural Programming)

Procedural programming uses a list of instructions to tell the computer what to do step-by-step.?
面向過程編程依賴 - 你猜到了- procedures,一個procedure包含一組要被進行計算的步驟, 面向過程又被稱為top-down languages, 就是程序從上到下一步步執行,一步步從上到下,從頭到尾的解決問題 。基本設計思路就是程序一開始是要著手解決一個大的問題,然后把一個大問題分解成很多個小問題或子過程,這些子過程再執行的過程再繼續分解直到小問題足夠簡單到可以在一個小步驟范圍內解決。

python面向對象詳解、這樣做的問題也是顯而易見的,就是如果你要對程序進行修改,對你修改的那部分有依賴的各個部分你都也要跟著修改, 舉個例子,如果程序開頭你設置了一個變量值 為1 , 但如果其它子過程依賴這個值 為1的變量才能正常運行,那如果你改了這個變量,那這個子過程你也要修改,假如又有一個其它子程序依賴這個子過程 , 那就會發生一連串的影響,隨著程序越來越大, 這種編程方式的維護難度會越來越高。?
所以我們一般認為, 如果你只是寫一些簡單的腳本,去做一些一次性任務,用面向過程的方式是極好的,但如果你要處理的任務是復雜的,且需要不斷迭代和維護 的, 那還是用面向對象最方便了。 ---引用大王博客。http://www.cnblogs.com/alex3714/articles/5188179.html

簡而言之,大概的意思就是,面向過程編程是從上到下代碼一次進行執行的,如果最上面的值有變動,會對下面的代碼邏輯產生一系列的反應,因此我們認為如果寫一些小的腳本編程,面向過程可以神勝任;如果是要寫一堆復雜的邏輯代碼,那么面向對象還是比較方便的。

面向對象編程

OOP編程是利用“類”和“對象”來創建各種模型來實現對真實世界的描述,使用面向對象編程的原因一方面是因為它可以使程序的維護和擴展變得更簡單,并且可以大大提高程序開發效率 ,另外,基于面向對象的程序可以使它人更加容易理解你的代碼邏輯,從而使團隊開發變得更從容。

?---引用大王博客。http://www.cnblogs.com/alex3714/articles/5188179.html

人生苦短我學python表情包,面向對象的幾個核心特性如下:

Class 類
一個類即是對一類擁有相同屬性的對象的抽象、藍圖、原型。在類中定義了這些對象的都具備的屬性(variables(data))、共同的方法,如下我們定義了一個角色(Role)類

# Author:Sean sir
class Role():def __init__(self,name,role,weapon,r_list,life_value=100,money=10000):self.r_list = r_listself.name = nameself.role = roleself.weapon = weaponself.life_value = life_valueself.money = moneydef shot(self):print('shooting...')def got_shot(self):print("ah...,I got  shot...!")def buy_gun(self,gun_name):print("just bought %s" %gun_name)

Object 對象?
一個對象即是一個類的實例化后實例,一個類必須經過實例化后方可在程序中調用,一個類可以實例化多個對象,每個對象亦可以有不同的屬性,就像人類是指所有人,每個人是指具體的對象,人與人之前有共性,亦有不同 ?---引用大王博客。http://www.cnblogs.com/alex3714/articles/5188179.html

所謂的對象是對一個類進行實例化后的一個物質,可以大概理解為,一個類是某些具有相同特征的物質的模板,然而一個對象是按照找個模板制作的一個物質

python輸出人生苦短?上帝造人,人的類是要有“五官、四肢、內臟等等而組成”,當造成了一個人后,那么這個人就是按照這個模板實例化出來的一個對象

class School( object ):def __init__(self, name, addr):self.name = nameself.addr = addrself.students = []self.teachets = []# 為學員辦理注冊手續def enroll(self, stu_obj):print('為學員%s辦理注冊手續!' % stu_obj)self.students.append(stu_obj)# 雇傭新的老師def hire(self, staff_obj):print( '成功雇傭心的員工%s' % staff_obj )self.teachets.append( staff_obj )
# 實例化一個學校對象
school = School( '老男孩', '沙河' )
# 調用學校里面的enroll方法
school.enroll('asdf')
#輸出
為學員asdf辦理注冊手續!

Encapsulation 封裝
在類中對數據的賦值、內部調用對外部用戶是透明的,這使類變成了一個膠囊或容器,里面包含著類的數據和方法?---引用大王博客。http://www.cnblogs.com/alex3714/articles/5188179.html

面向對象的程序設計中,某個類把所需要的數據(也可以說是類的屬性)和對數據的操作(也可以說是類的行為)全部都封裝在類中,分別稱為類的成員變量和方法(或成員函數)。這種把成員變量和成員函數封裝在一起的編程特性稱為封裝。

Inheritance 繼承
一個類可以派生出子類,在這個父類里定義的屬性、方法自動被子類繼承 父親和兒子的關系大概就是這樣的

# 父類
class SchoolMember(object):def __init__(self, name, age, sex):self.name = nameself.sex = sexself.age = agedef tell(self):pass
# 子類
class Teacher(SchoolMember):def __init__(self, name, age, sex, salary, course):super(Teacher, self).__init__(name, age, sex)self.salary = salaryself.course = coursedef tell(self):print('''
            ------------Teacher info of %s------------Name:%sAge:%sSex:%sSalary:%sCourse:%s''' % (self.name, self.name, self.age, self.sex, self.salary, self.course)
        )def teach(self):print('%s is teaching course [%s]' % (self.name, self.course))
# 實例化一個老師對象
t1 = Teacher('Oldboy', 56, 'MF', 20000, 'python')
# 調用老師對象里面的tell方法,并在Teacher中調用父類的SchoolMember中的學校名稱
t1.tell()
# 輸出------------Teacher info of Oldboy------------Name:OldboyAge:56Sex:MFSalary:20000Course:python

python面向對象的領悟。Polymorphism 多態
態是面向對象的重要特性,簡單點說:“一個接口,多種實現”,指一個基類中派生出了不同的子類,且每個子類在繼承了同樣的方法名的同時又對父類的方法做了不同的實現,這就是同一種事物表現出的多種形態。
編程其實就是一個將具體世界進行抽象化的過程,多態就是抽象化的一種體現,把一系列具體事物的共同點抽象出來, 再通過這個抽象的事物, 與不同的具體事物進行對話。
對不同類的對象發出相同的消息將會有不同的行為。比如,你的老板讓所有員工在九點鐘開始工作, 他只要在九點鐘的時候說:“開始工作”即可,而不需要對銷售人員說:“開始銷售工作”,對技術人員說:“開始技術工作”, 因為“員工”是一個抽象的事物, 只要是員工就可以開始工作,他知道這一點就行了。至于每個員工,當然會各司其職,做各自的工作。
多態允許將子類的對象當作父類的對象使用,某父類型的引用指向其子類型的對象,調用的方法是該子類型的方法。這里引用和調用方法的代碼編譯前就已經決定了,而引用所指向的對象可以在運行期間動態綁定

?

面向對象編程(Object-Oriented Programming?)介紹


對于編程語言的初學者來講,OOP不是一個很容易理解的編程方式,大家雖然都按老師講的都知道OOP的三大特性是繼承、封裝、多態,并且大家也都知道了如何定義類、方法等面向對象的常用語法,但是一到真正寫程序的時候,還是很多人喜歡用函數式編程來寫代碼,特別是初學者,很容易陷入一個窘境就是“我知道面向對象,我也會寫類,但我依然沒發現在使用了面向對象后,對我們的程序開發效率或其它方面帶來什么好處,因為我使用函數編程就可以減少重復代碼并做到程序可擴展了,為啥子還用面向對象?”。 對于此,我個人覺得原因應該還是因為你沒有充分了解到面向對象能帶來的好處,今天我就寫一篇關于面向對象的入門文章,希望能幫大家更好的理解和使用面向對象編程。 ?
無論用什么形式來編程,我們都要明確記住以下原則:
  1. 寫重復代碼是非常不好的低級行為
  2. 你寫的代碼需要經常變更?
開發正規的程序跟那種寫個運行一次就扔了的小腳本一個很大不同就是,你的代碼總是需要不斷的更改,不是修改bug就是添加新功能等,所以為了日后方便程序的修改及擴展,你寫的代碼一定要遵循易讀、易改的原則(專業數據叫可讀性好、易擴展)。
如果你把一段同樣的代碼復制、粘貼到了程序的多個地方以實現在程序的各個地方調用 這個功能,那日后你再對這個功能進行修改時,就需要把程序里多個地方都改一遍,這種寫程序的方式是有問題的,因為如果你不小心漏掉了一個地方沒改,那可能會導致整個程序的運行都 出問題。 因此我們知道 在開發中一定要努力避免寫重復的代碼,否則就相當于給自己再挖坑。
還好,函數的出現就能幫我們輕松的解決重復代碼的問題,對于需要重復調用的功能,只需要把它寫成一個函數,然后在程序的各個地方直接調用這個函數名就好了,并且當需要修改這個功能時,只需改函數代碼,然后整個程序就都更新了。
其實OOP編程的主要作用也是使你的代碼修改和擴展變的更容易,那么小白要問了,既然函數都能實現這個需求了,還要OOP干毛線用呢? 呵呵,說這話就像,古時候,人們打仗殺人都用刀,后來出來了槍,它的主要功能跟刀一樣,也是殺人,然后小白就問,既然刀能殺人了,那還要槍干毛線,哈哈,顯而易見,因為槍能更好更快更容易的殺人。函數編程與OOP的主要區別就是OOP可以使程序更加容易擴展和易更改。
小白說,我讀書少,你別騙我,口說無憑,證明一下,好吧,那我們就下面的例子證明給小白看。?
相信大家都打過CS游戲吧,我們就自己開發一個簡單版的CS來玩一玩。
        ---引用大王博客。http://www.cnblogs.com/alex3714/articles/5188179.html

暫不考慮開發場地等復雜的東西,我們先從人物角色下手, 角色很簡單,就倆個,恐怖份子、警察,他們除了角色不同,其它基本都 一樣,每個人都有生命值、武器等。 咱們先用非OOP的方式寫出游戲的基本角色?

#role 1
name = 'Alex'
role = 'terrorist'
weapon = 'AK47'
life_value = 100#rolw 2
name2 = 'Jack'
role2 = 'police'
weapon2 = 'B22'
life_value2 = 100

python3 面向對象編程,上面定義了一個恐怖份子Alex和一個警察Jack,但只2個人不好玩呀,一干就死了,沒意思,那我們再分別創建一個恐怖分子和警察吧,

#role 1
name = 'Alex'
role = 'terrorist'
weapon = 'AK47'
life_value = 100
money = 10000#rolw 2
name2 = 'Jack'
role2 = 'police'
weapon2 = 'B22'
life_value2 = 100
money2 = 10000#role 3
name3 = 'Rain'
role3 = 'terrorist'
weapon3 = 'C33'
life_value3 = 100
money3 = 10000#rolw 4
name4 = 'Eric'
role4 = 'police'
weapon4 = 'B51'
life_value4 = 100
money4 = 10000
4個角色雖然創建好了,但是有個問題就是,每創建一個角色,我都要單獨命名,name1,name2,name3,name4…,后面的調用的時候這個變量名你還都得記著,要是再讓多加幾個角色,估計調用時就很容易弄混啦,所以我們想一想,能否所有的角色的變量名都是一樣的,但調用的時候又能區分開分別是誰??
當然可以,我們只需要把上面的變量改成字典的格式就可以啦。
roles = {1:{'name':'Alex','role':'terrorist','weapon':'AK47','life_value': 100,'money': 15000,},2:{'name':'Jack','role':'police','weapon':'B22','life_value': 100,'money': 15000,},3:{'name':'Rain','role':'terrorist','weapon':'C33','life_value': 100,'money': 15000,},4:{'name':'Eirc','role':'police','weapon':'B51','life_value': 100,'money': 15000,},
}
很好,這個以后調用這些角色時只需要roles[1],roles[2]就可以啦,角色的基本屬性設計完了后,我們接下來為每個角色開發以下幾個功能
  1. 被打中后就會掉血的功能
  2. 開槍功能
  3. 換子彈
  4. 買槍
  5. 跑、走、跳、下蹲等動作
  6. 保護人質(僅適用于警察)
  7. 不能殺同伴
  8. 。。。

我們可以把每個功能寫成一個函數,類似如下:?

def shot(by_who):#開了槍后要減子彈數pass
def got_shot(who):#中槍后要減血who[‘life_value’] -= 10pass
def buy_gun(who,gun_name):#檢查錢夠不夠,買了槍后要扣錢pass
so far so good, 繼續按照這個思路設計,再完善一下代碼,游戲的簡單版就出來了,但是在往下走之前,我們來看看上面的這種代碼寫法有沒有問題,至少從上面的代碼設計中,我看到以下幾點缺陷:
  1. 每個角色定義的屬性名稱是一樣的,但這種命名規則是我們自己約定的,從程序上來講,并沒有進行屬性合法性檢測,也就是說role 1定義的代表武器的屬性是weapon, role 2 ,3,4也是一樣的,不過如果我在新增一個角色時不小心把weapon 寫成了wepon , 這個程序本身是檢測 不到的
  2. terrorist 和police這2個角色有些功能是不同的,比如police是不能殺人質的,但是terrorist可能,隨著這個游戲開發的更復雜,我們會發現這2個角色后續有更多的不同之處, 但現在的這種寫法,我們是沒辦法 把這2個角色適用的功能區分開來的,也就是說,每個角色都可以直接調用任意功能,沒有任何限制。
  3. 我們在上面定義了got_shot()后要減血,也就是說減血這個動作是應該通過被擊中這個事件來引起的,我們調用get_shot(),got_shot()這個函數再調用每個角色里的life_value變量來減血。 但其實我不通過got_shot(),直接調用角色roles[role_id][‘life_value’] 減血也可以呀,但是如果這樣調用的話,那可以就是簡單粗暴啦,因為減血之前其它還應該判斷此角色是否穿了防彈衣等,如果穿了的話,傷害值肯定要減少,got_shot()函數里就做了這樣的檢測,你這里直接繞過的話,程序就亂了。 因此這里應該設計 成除了通過got_shot(),其它的方式是沒有辦法給角色減血的,不過在上面的程序設計里,是沒有辦法實現的。?
  4. 現在需要給所有角色添加一個可以穿防彈衣的功能,那很顯然你得在每個角色里放一個屬性來存儲此角色是否穿 了防彈衣,那就要更改每個角色的代碼,給添加一個新屬性,這樣太low了,不符合代碼可復用的原則
上面這4點問題如果不解決,以后肯定會引出更大的坑,有同學說了,解決也不復雜呀,直接在每個功能調用時做一下角色判斷啥就好了,沒錯,你要非得這么霸王硬上弓的搞也肯定是可以實現的,那你自己就開發相應的代碼來對上面提到的問題進行處理好啦。 但這些問題其實能過OOP就可以很簡單的解決。

?

之前的代碼改成用OOP中的“類”來實現的話如下:??

人生苦短我用python表情包??

class Role(object):def __init__(self,name,role,weapon,life_value=100,money=15000):self.name = nameself.role = roleself.weapon = weaponself.life_value = life_valueself.money = moneydef shot(self):print("shooting...")def got_shot(self):print("ah...,I got shot...")def buy_gun(self,gun_name):print("just bought %s" %gun_name)r1 = Role('Alex','police','AK47’) #生成一個角色
r2 = Role('Jack','terrorist','B22’)  #生成一個角色
先不考慮語法細節,相比函數式寫法,上面用面向對象中的類來寫最直接的改進有以下2點:
  1. 代碼量少了近一半
  2. 角色和它所具有的功能可以一目了然看出來
接下來我們一起分解一下上面的代碼分別 是什么意思 :
class Role(object): #定義一個類, class是定義類的語法,Role是類名,(object)是新式類的寫法,必須這樣寫,以后再講為什么def __init__(self,name,role,weapon,life_value=100,money=15000): #初始化函數,在生成一個角色時要初始化的一些屬性就填寫在這里self.name = name #__init__中的第一個參數self,和這里的self都 是什么意思? 看下面解釋self.role = roleself.weapon = weaponself.life_value = life_valueself.money = money
上面的這個__init__()叫做初始化方法(或構造方法), 在類被調用時,這個方法(雖然它是函數形式,但在類中就不叫函數了,叫方法)會自動執行,進行一些初始化的動作,所以我們這里寫的__init__(self,name,role,weapon,life_value=100,money=15000)就是要在創建一個角色時給它設置這些屬性,那么這第一個參數self是干毛用的呢??
初始化一個角色,就需要調用這個類一次:?
r1 = Role('Alex','police','AK47’) #生成一個角色 , 會自動把參數傳給Role下面的__init__(...)方法
r2 = Role('Jack','terrorist','B22’)  #生成一個角色

我們看到,上面的創建角色時,我們并沒有給__init__傳值,程序也沒未報錯,是因為,類在調用它自己的__init__(…)時自己幫你給self參數賦值了,?

r1 = Role('Alex','police','AK47’) #此時self 相當于 r1 ,  Role(r1,'Alex','police','AK47’)
r2 = Role('Jack','terrorist','B22’)#此時self 相當于 r2, Role(r2,'Jack','terrorist','B22’)
為什么這樣子?你拉著我說你有些猶豫,怎么會這樣子?
你執行r1?=?Role('Alex','police','AK47)時,python的解釋器其實干了兩件事:
  1. 在內存中開辟一塊空間指向r1這個變量名
  2. 調用Role這個類并執行其中的__init__(…)方法,相當于Role.__init__(r1,'Alex','police',AK47’),這么做是為什么呢? 是為了把'Alex','police',’AK47’這3個值跟剛開辟的r1關聯起來,是為了把'Alex','police',’AK47’這3個值跟剛開辟的r1關聯起來,是為了把'Alex','police',’AK47’這3個值跟剛開辟的r1關聯起來,重要的事情說3次, 因為關聯起來后,你就可以直接r1.name, r1.weapon 這樣來調用啦。所以,為實現這種關聯,在調用__init__方法時,就必須把r1這個變量也傳進去,否則__init__不知道要把那3個參數跟誰關聯呀。
  3. 明白了么哥?所以這個__init__(…)方法里的,self.name = name , self.role = role 等等的意思就是要把這幾個值 存到r1的內存空間里。
如果還不明白的話,哥,去測試一下智商吧, 應該不會超過70,哈哈。
為了暴露自己的智商,此時你假裝懂了,但又問, __init__(…)我懂了,但后面的那幾個函數,噢 不對,后面那幾個方法 為什么也還需要self參數么? 不是在初始化角色的時候 ,就已經把角色的屬性跟r1綁定好了么??
good question, 先來看一下上面類中的一個buy_gun的方法:?
def buy_gun(self,gun_name):print(“%s has just bought %s” %(self.name,gun_name) )

上面這個方法通過類調用的話要寫成如下:

r1?=?Role('Alex','police','AK47')

r1.buy_gun("B21”) #python 會自動幫你轉成 Role.buy_gun(r1,”B21")
執行結果
#Alex has just bought B21?
依然沒給self傳值 ,但Python還是會自動的幫你把r1 賦值給self這個參數, 為什么呢? 因為,你在buy_gun(..)方法中可能要訪問r1的一些其它屬性呀, 比如這里就訪問 了r1的名字,怎么訪問呢?你得告訴這個方法呀,于是就把r1傳給了這個self參數,然后在buy_gun里調用 self.name 就相當于調用r1.name 啦,如果還想知道r1的生命值 有多少,直接寫成self.life_value就可以了。 說白了就是在調用類中的一個方法時,你得告訴人家你是誰。
好啦, 總結一下2點:
  1. 上面的這個r1?=?Role('Alex','police','AK47)動作,叫做類的“實例化”, 就是把一個虛擬的抽象的類,通過這個動作,變成了一個具體的對象了, 這個對象就叫做實例
  2. 剛才定義的這個類體現了面向對象的第一個基本特性,封裝,其實就是使用構造方法將內容封裝到某個具體對象中,然后通過對象直接或者self間接獲取被封裝的內容
執行結果
#Alex has just bought B21?
依然沒給self傳值 ,但Python還是會自動的幫你把r1 賦值給self這個參數, 為什么呢? 因為,你在buy_gun(..)方法中可能要訪問r1的一些其它屬性呀, 比如這里就訪問 了r1的名字,怎么訪問呢?你得告訴這個方法呀,于是就把r1傳給了這個self參數,然后在buy_gun里調用 self.name 就相當于調用r1.name 啦,如果還想知道r1的生命值 有多少,直接寫成self.life_value就可以了。 說白了就是在調用類中的一個方法時,你得告訴人家你是誰。
好啦, 總結一下2點:
  1. 上面的這個r1?=?Role('Alex','police','AK47)動作,叫做類的“實例化”, 就是把一個虛擬的抽象的類,通過這個動作,變成了一個具體的對象了, 這個對象就叫做實例
  2. 剛才定義的這個類體現了面向對象的第一個基本特性,封裝,其實就是使用構造方法將內容封裝到某個具體對象中,然后通過對象直接或者self間接獲取被封裝的內容

python和java,?---引用大王博客。http://www.cnblogs.com/alex3714/articles/5188179.html

?


實例化                                 

一個類變成一個對象的過程叫做實例化

構造函數                                ??

作用:在實例化一個對象時候,做一些類的初始化的工作,此方法會自動執行

class SchoolMember(object):
  # 構造函數
def __init__(self, name, age, sex):self.name = nameself.sex = sexself.age = agedef tell(self):pass class Student(SchoolMember):
  # 構造函數
def __init__(self, name, age, sex, stu_id, grade):super( Student, self ).__init__( name, age, sex ) # 這句話的意思是,集成父類的init的方法,并在此基礎上增加功能self.stu_id = stu_idself.grade = gradeprint(self.name, self.sex, self.age,self.stu_id,self.grade)def tell(self):print('''------------Student info of %s------------Name:%sAge:%sSex:%sStu_id:%sGrade:%s''' % (self.name, self.name, self.age, self.sex, self.stu_id, self.grade))def pay_tuition(self, amount):print( '%s has paid tution for $%s' % (self.name, amount) ) # 輸出 s1 = Student( 'sean', 23, 'MF', 1001, 'Python' )

構造函數的工作過程:

java面向對象,  

如果不傳入self參數的話,那么就成了name=‘sean’、sex=‘M’、age=22,但是這樣賦值的時候,就成了局部變量,外部沒有辦法調用,如果想調用的話有的人說了

可以是用globule一下,但是這樣就寫死了,當在使用這個類實例化第二個方法的是,那么第一個方法就被覆蓋了,其實可以說當第一個實例化完成函數結束的時候,變量就沒了,所以還是需要傳入一個值,把這個參數寫活。

?實例變量與類變量                            

實例變量:實例變量又稱靜態變量,那么類方法就是動態變量

人生苦短我用python梗。    作用域:實力本身

    作用:用來描述某個具體對象的特定屬性

類變量:類變量也成靜態變量

    作用域:類本身,包括被實例化后的實例

    作用:所有通過這個類實例化出來的對象共同擁有的屬性

1.同一個變量在是實例中存在同時也在類中存在,那么尋找方的優先級是先從實例變量中找,再從類變量里面查找

# Author:Sean sir
class test(object):name = 'alex'def __init__(self,name,age):self.name = nameself.age = age
Test = test('sean',22)
print(Test.name)
print(Test.age)
# 輸出
sean
22

2.修改實例變量值

# Author:Sean sir
class test(object):name = 'alex'def __init__(self,name,age):self.name = nameself.age = ageTest = test('sean',22)
Test.name = 'Jack'
print(Test.name)
print(Test.age)
# 輸出
Jack
22

3.新增加一個實例變量值

# Author:Sean sir
class test(object):name = 'alex'def __init__(self,name,age):self.name = nameself.age = ageTest = test('sean',22)
Test.sex = 'M'
print(Test.name)
print(Test.sex)
# 輸出
sean
M

4.刪除一個實例變量值

# Author:Sean sir
class test(object):name = 'alex'def __init__(self,name,age):self.name = nameself.age = age
Test1 = test('jack',23)
print(Test1.name)
print(Test1.age)Test2 = test('sean',22)
print(Test2.age)
del Test2.age
print(Test2.name)
print(Test2.age)
# 輸出
/usr/local/bin/python3.5 /Applications/PyCharm.app/Contents/helpers/pycharm/utrunner.py /Users/sean/python/s14/課堂/d6/類作業.py true
Testing started at 上午10:26 ...
Traceback (most recent call last):File "/Applications/PyCharm.app/Contents/helpers/pycharm/utrunner.py", line 121, in <module>modules = [loadSource(a[0])]File "/Applications/PyCharm.app/Contents/helpers/pycharm/utrunner.py", line 43, in loadSourcemodule = imp.load_source(moduleName, fileName)File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/imp.py", line 172, in load_sourcemodule = _load(spec)File "<frozen importlib._bootstrap>", line 693, in _loadFile "<frozen importlib._bootstrap>", line 673, in _load_unlockedFile "<frozen importlib._bootstrap_external>", line 665, in exec_moduleFile "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removedFile "/Users/sean/python/s14/課堂/d6/類作業.py", line 17, in <module>print(Test.age)
AttributeError: 'test' object has no attribute 'age'
jack
23
22
seanProcess finished with exit code 1

?5.更改一個實例變量

   在一個實例中更改了類變量是不影響其他實例對類變量的調用的;內部意思是,在下面實例Test內存中加了一個sex變量等于‘改類變量’,當Test1調用sex變量的時候,發現自己的實例內存中有sex這個變量值,所以就成了‘改類變量’;Test2調用的時候,自己實例內存中沒有,自然就調用類中的sex變量值嘍

# Author:Sean sir
class test(object):sex = 'M'def __init__(self,name,age):self.name = nameself.age = age
Test1 = test('jack',23)
Test1.sex = '改類變量'
print(Test1.name,Test1.age,Test1.sex)Test2 = test('sean',22)
print(Test2.name,Test2.age,Test2.sex)
# 輸出
Testing started at 上午10:31 ...
jack 23 改類變量
sean 22 M

?6.同時更改一個類變量和一個實例變量,并且更改的這個變量在類和實例中都在

# Author:Sean sir
class test(object):sex = 'M'def __init__(self,name,age):self.name = nameself.age = agetest.sex = 'F'
Test = test('jack',23)
Test.sex = '改類變量'
print(Test.name,Test.age,Test.sex)Test = test('sean',22)
print(Test.name,Test.age,Test.sex)
# 輸出
jack 23 改類變量
sean 22 F

7.類變量作用

# Author:Sean sir
class person(object):country = '中國'def __init__(self,name,age):self.name = nameself.age = ageP1 = person('sean',22)
print(P1.name,P1.age,P1.country)
# 更改國籍

P1.country = '泰國'
print(P1.name,P1.age,P1.country)#輸出
sean 22 中國
sean 22 泰國

有的人說,下面這種做法也是可以做到的:

# Author:Sean sir
class person(object):def __init__(self,name,age,country = '中國'):self.name = nameself.age = ageself.country = countryP1 = person('sean',22)
print(P1.name,P1.age,P1.country)
# 更改國籍

P1.country = '泰國'
print(P1.name,P1.age,P1.country)#輸出
sean 22 中國
sean 22 泰國

沒錯,確實能做到,但是使用類變量是只有一個內存變量地址,如果使用實例變量全國有13億人口那么將產生13個內存地址存放實例變量,這樣是不是有點浪費?

析構函數                                

?作用:在實例釋放或銷毀時自動執行的結尾的函數,通常用于做一些掃尾工作,比如:關閉一些數據庫鏈接打卡的臨時文等。

第一種:程序運行結束,退出后析構函數執行

# Author:Sean sir
class Role():r_list= [4,5,6]def __init__(self,name,role,weapon,life_value=100,money=10000):self.name = nameself.role = roleself.weapon = weapon# 私有屬性# self.__life_value = life_valueself.life_value = life_valueself.money = money# 析構函數def __del__(self):print('%s 徹底死了!' %self.name)def shot(self):print('shooting...')def got_shot(self):# self.__life_value -= 49print("ah...,I got  shot...!")def buy_gun(self,gun_name):print("just bought %s" %gun_name)# 析構函數
r1 = Role('Alex','police','Ak47')
r2 = Role('金角大王','police','B22')
# 輸出
Alex 徹底死了!
金角大王 徹底死了!

第二種:實例被刪除釋放后,析構函數執行

# Author:Sean sir
class Role():r_list= [4,5,6]def __init__(self,name,role,weapon,life_value=100,money=10000):self.name = nameself.role = roleself.weapon = weapon# 私有屬性# self.__life_value = life_valueself.life_value = life_valueself.money = money# 析構函數def __del__(self):print('%s 徹底死了!' %self.name)def shot(self):print('shooting...')def got_shot(self):# self.__life_value -= 49print("ah...,I got  shot...!")def buy_gun(self,gun_name):print("just bought %s" %gun_name)# 析構函數
r1 = Role('Alex','police','Ak47')
r1.buy_gun('B35')
del r1
r2 = Role('金角大王','police','B22')
r2.got_shot()
# 輸出
just bought B35
Alex 徹底死了!
ah...,I got  shot...!
金角大王 徹底死了!

私有方法和私有屬性?                           ?

私有就是說只有在實例內部調用,如果想在實例外調用,那么需要在實例內部寫一個方法進行調用,不管是私有方法還是私有屬性都是一樣的

# Author:Sean sir
class Role():r_list= [4,5,6]def __init__(self,name,role,weapon,life_value=100,money=10000):self.name = nameself.role = roleself.weapon = weapon# 私有屬性self.__life_value = life_valueself.life_value = life_valueself.money = money# 私有屬性調用def show_statu(self):print('%s status: life_val[%s] money[%s]' %(self.name,self.__life_value,self.money))def shot(self):print('shooting...')def got_shot(self):# self.__life_value -= 49print("ah...,I got  shot...!")def buy_gun(self,gun_name):print("just bought %s" %gun_name)# 私有方法def __change_firearms(self,weapon):self.weapon = weaponprint('%s 更換槍械成功,現在槍械為%s' %(self.name,self.weapon))# 私有方法調用def chose_change_firearms(self,weapon):self.__change_firearms(weapon)# 私有屬性(變量) 使用__就能變為私有,調用要在內部調用
r1 = Role('Alex','police','Ak47')
r1.got_shot()
r1.show_statu()
# 私有方法 使用__就能把一個函數變為私有,調用在內部調用
r1 = Role('Alex','police','Ak47')
print(r1.weapon)
r1.chose_change_firearms('散彈槍')# 輸出
ah...,I got  shot...!
Alex status: life_val[100] money[10000]
Ak47
Alex 更換槍械成功,現在槍械為散彈槍

類的繼承                                    

?


?

?

面向對象編程 (OOP) 語言的一個主要功能就是“繼承”。繼承是指這樣一種能力:它可以使用現有類的所有功能,并在無需重新編寫原來的類的情況下對這些功能進行擴展。

通過繼承創建的新類稱為“子類”或“派生類”。

被繼承的類稱為“基類”、“父類”或“超類”。

繼承的過程,就是從一般到特殊的過程。

要實現繼承,可以通過“繼承”(Inheritance)和“組合”(Composition)來實現。

在某些 OOP 語言中,一個子類可以繼承多個基類。但是一般情況下,一個子類只能有一個基類,要實現多重繼承,可以通過多級繼承來實現。

繼承概念的實現方式有三類:實現繼承、接口繼承和可視繼承。

??????????實現繼承是指使用基類的屬性和方法而無需額外編碼的能力;
??????????接口繼承是指僅使用屬性和方法的名稱、但是子類必須提供實現的能力;
??????????可視繼承是指子窗體(類)使用基窗體(類)的外觀和實現代碼的能力。

在考慮使用繼承時,有一點需要注意,那就是兩個類之間的關系應該是“屬于”關系。例如,Employee 是一個人,Manager 也是一個人,因此這兩個類都可以繼承 Person 類。但是 Leg 類卻不能繼承 Person 類,因為腿并不是一個人。

抽象類僅定義將由子類創建的一般屬性和方法。

OO開發范式大致為:劃分對象→抽象類→將類組織成為層次化結構(繼承和合成) →用類與實例進行設計和實現幾個階段。

?

繼承示例
---引用大王博客。http://www.cnblogs.com/alex3714/articles/5188179.html

?

?


?

優點?
新的實現很容易,因為大部分是繼承而來的?
很容易修改和擴展已有的實現?

缺點?
打破了封裝,因為基類向子類暴露了實現細節?
白盒重用,因為基類的內部細節通常對子類是可見的?
當父類的實現改變時可能要相應的對子類做出改變?
不能在運行時改變由父類繼承來的實現?
由此可見,組合比繼承具有更大的靈活性和更穩定的結構,一般情況下應該優先考慮組合。

只有當下列條件滿足時才考慮使用繼承:?
子類是一種特殊的類型,而不只是父類的一個角色?
子類的實例不需要變成另一個類的對象?
子類擴展,而不是覆蓋或者使父類的功能失效
?

?

?繼承父類的方法

# Author:Sean sir
class people:def __init__(self,name,age):self.name = nameself.age = agedef eat(self):print('%s is eatting!' %self.name)def sleep(self):print('%s is sleepping!' %self.name)class Man(people):def piao(self):print('%s piaoing ..... Done!' %self.name)def sleep(self):people.sleep(self)print('不要睡了!寶貝!')class Women(people):def get_birth(self):print('%s is born a boby...' %self.name)# 測試父類
print('-----測試父類-------')
p1 = people('alex',33)
p1.sleep()
p1.eat()
# 調用子類Man
print('-----調用子類Man-------')
m1 = Man('ChenRongHua',22)
m1.sleep()
m1.eat()
m1.piao()# 調用子類Women
print('-----調用子類Women-------')
w1 = Women('NiuHanYang',23)
w1.get_birth()
w1.sleep()
w1.eat()
# 輸出
-----測試父類-------
alex is sleepping!
alex is eatting!
-----調用子類Man-------
ChenRongHua is sleepping!
不要睡了!寶貝!
ChenRongHua is eatting!
ChenRongHua piaoing ..... Done!
-----調用子類Women-------
NiuHanYang is born a boby...
NiuHanYang is sleepping!
NiuHanYang is eatting!

?

?

重構父類方法

# Author:Sean sir
class people:def __init__(self,name,age):self.name = nameself.age = agedef eat(self):print('%s is eatting!' %self.name)def sleep(self,sleep_time):print('%s is sleepping %s!' %(self.name,sleep_time))class Man(people):def piao(self):print('%s piaoing ..... Done!' %self.name)def sleep(self,sleep_time2):people.sleep(self,sleep_time=sleep_time2)print('不要睡了!寶貝!')m1 = Man('alex',22)
m1.sleep(2)# 輸出
alex is sleepping 2!
不要睡了!寶貝!

?

繼承父類的同時,重構父類的構造方法

# Author:Sean sir
class people:def __init__(self,name,age):self.name = nameself.age = agedef eat(self):print('%s is eatting!' %self.name)def sleep(self):print('%s is sleepping!' %self.name)class Man(people):def __init__(self,name,age,sex,salary):super(Man,self).__init__(name,age)  # 這種是新式類寫法,一會在探討新舊的區別self.sex = sexself.salary = salarydef piao(self):print('%s piaoing ..... Done!' %self.name)def sleep(self):people.sleep(self)print('不要睡了!寶貝,你發了$%s的工資啊,晚上出去擼串去!' %self.salary)# 測試父類
print('-----測試父類-------')
p1 = people('alex',33)
p1.sleep()# 調用子類Man
print('-----調用子類Man-------')
m1 = Man('ChenRongHua',22,'F',2999)
m1.sleep()# 輸出
-----測試父類-------
alex is sleepping!
-----調用子類Man-------
ChenRongHua is sleepping!
不要睡了!寶貝,你發了$2999的工資啊,晚上出去擼串去!

?

?來一個多繼承,一個孩子生下來集成父親的某種功能又集成母親的某些功能:

# Author:Sean sir
class people:def __init__(self,name,age):self.name = nameself.age = agedef eat(self):print('%s is eatting!' %self.name)def sleep(self):print('%s is sleepping!' %self.name)
class Relation(object):def make_friends(self,obj):print( '%s and %s 交朋友!' % (self.name,obj.name))
class Man(people):def __init__(self,name,age,sex,salary):super(Man,self).__init__(name,age)  # 這種是新式類寫法,一會在探討新舊的區別self.sex = sexself.salary = salarydef piao(self):print('%s piaoing ..... Done!' %self.name)def sleep(self):people.sleep(self)print('不要睡了!寶貝,你發了$%s的工資啊,晚上出去擼串去!' %self.salary)
class Woman(people,Relation):def __init__(self, name, age, sex, salary):super(Woman, self).__init__(name, age)self.sex = sexself.salary = salary
m1 = Man('sean',23,'M',2499)
w1 = Woman('airc',22,'F',230)
w1.make_friends(m1)
# 輸出
airc and sean 交朋友!

?新式類和經典類的構造方法區別                        

?首先來看一張圖,我們有4個類ABCD,B集成A,C集成A,D集成B和C

?py3中經典類和新式類都是統一按廣度優先來繼承的,py2中經典類是按深度優先來繼承的,新式類是按廣度優先來繼承的,看代碼:

  首先看一下新式類py3構造方法的引用順序

# Author:Sean sir
class A(object):def __init__(self):print('A')class B(A):def __init__(self):print('B')class C(A):def __init__(self):print('C')class D(B,C):passtest = D()
# 輸出
B
View Code

我們把B和C掉換位置

# Author:Sean sir
class A(object):def __init__(self):print('A')class B(A):def __init__(self):print('B')class C(A):def __init__(self):print('C')class D(C,B):passtest = D()
# 輸出
C
View Code

注釋掉C的構造方法

# Author:Sean sir
class A(object):def __init__(self):print('A')class B(A):def __init__(self):print('B')class C(A):# def __init__(self):#     print('C')passclass D(C,B):passtest = D()
# 輸出
B
View Code

注釋掉B的構造方法

# Author:Sean sir
class A(object):def __init__(self):print('A')class B(A):# def __init__(self):#     print('B')passclass C(A):# def __init__(self):#     print('C')passclass D(C,B):passtest = D()
# 輸出
A
View Code

?

再看一下經典類在python3中構造方法的引用順序

# Author:Sean sirclass A:def __init__(self):print('A')class B(A):def __init__(self):print('B')class C(A):def __init__(self):print('C')class D(C,B):passtest = D()'''
output
C
'''
View Code

去掉C中的構造方法

# Author:Sean sirclass A:def __init__(self):print('A')class B(A):def __init__(self):print('B')class C(A):passclass D(C,B):passtest = D()'''
output
B
'''
View Code

去掉B中的構造方法

# Author:Sean sirclass A:def __init__(self):print('A')class B(A):passclass C(A):passclass D(C,B):passtest = D()'''
output
A
'''
View Code

當然不管父類的構造方法怎么變,如果子類本身有構造方法,那么都會走自身的構造方法

我們可以看到 在py3中不管是經典類還是新式類都會秉行廣度優先的規則進行引用

?

?

我們在來看一下在py2中經典類構造方法的引用順序:?

# Author:Sean sirclass A:def __init__(self):print('A')class B(A):def __init__(self):print('B')class C(A):def __init__(self):print('C')class D(B,C):passtest = D()'''
output
B
'''
View Code

注釋掉B的構造方法

# Author:Sean sirclass A:def __init__(self):print('A')class B(A):passclass C(A):def __init__(self):print('C')class D(B,C):passtest = D()'''
output
A
'''
View Code

注釋掉A的構造方法

# Author:Sean sirclass A:passclass B(A):passclass C(A):def __init__(self):print('C')class D(B,C):passtest = D()'''
output
C
'''
View Code

?

我們在來看一下在py2中新式類的構造方法的引用順序:

# Author:Sean sirclass A(object):def __init__(self):print('A')class B(A):def __init__(self):print('B')class C(A):def __init__(self):print('C')class D(B,C):passtest = D()'''
output
B
'''
View Code

注釋掉B的構造方法

# Author:Sean sirclass A(object):def __init__(self):print('A')class B(A):passclass C(A):def __init__(self):print('C')class D(B,C):passtest = D()'''
output
C
'''
View Code

注釋掉C的構造方法

# Author:Sean sirclass A(object):def __init__(self):print('A')class B(A):passclass C(A):passclass D(B,C):passtest = D()'''
output
A
'''
View Code

我們總結一下,新式類在py2中構造方法的引用順序:

?我們看到在py2中新式類是秉行著廣度優先的規則進行引用的

在py2中經典類是秉性深度優先的規則進行構造函數調用的

?

?

?

?

?

?

?

?

?

?

?

?

?

?

轉載于:https://www.cnblogs.com/xinzhiyu/p/5820143.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/167461.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息