Python 【類與對象】


類與對象

把類的個例就叫做實例 (instance),可理解為“實際的例子”
類是某個特定的群體,實例是群體中某個具體的個體

Python中的對象等於類和實例的集合:即類可以看作是對象,實例也可以看作是對象,
比如列表list是個類對象,[1,2]是個實例對象,它們都是對象
“萬事萬物,皆為對象”

類的創建和調用

類的創建
類名的首字母要大寫

1 class Chinese:      # 創建一個類
2     eye = 'black'
3 
4     def eat(self):   #參數self的特殊之處:在定義時不能丟,在調用時要忽略
5         print('吃飯,選擇用筷子。')
6 
7 wu = Chinese()   # 類的實例化
8 print(wu.eye)   # 實例調用類屬性
9 wu.eat()  # 調用類中的方法(傳參不用管self)

print(type(wu))

<class '__main__.Chinese'> #驗證了wufeng屬於Chinese這個類
print(wu)
<__main__.Chinese object at 0x7f295682d400> #Chinese類的一個實例對象(object),后面的一串字符表示這個對象的內存地址


#類中創建的屬性和方法可以被其所有的實例調用,
而且,實例的數目在理論上是無限的。
我們可以同時“新建”多個實例

類也被稱為“實例工廠”,因其為所有實例提供了一套藍圖(即預先設定好有什么屬性和方法)

創建類的兩個關鍵點
一 。特殊參數:self

那么如果想在類的內部調用類屬性,而實例又還沒創建之前,我們就需要有個變量先代替實例接收數據,這個變量就是參數self。

 

1 class Chinese:
2 
3     name = ''  # 類屬性name
4 
5     def say(self):     
6         print(self.name + '是中國人')
7 
8 person = Chinese()   # 創建Chinese的實例person
9 person.say()         # 調用實例方法

 

當最后一行代碼運行時,實例person會像參數一樣傳給self,替換掉self,self.name等價於person.name
person.name就相當於調用了類屬性name(即'吳'),然后跑完整個方法

相當於以下:

 1 class Chinese:
 2 
 3     name = ''  # 類屬性name
 4 
 5     def say(person):     
 6         print(person.name + '是中國人')
 7 
 8 person = Chinese()   # 創建Chinese的實例person
 9 person.say()         # 調用實例方法
10 吳是中國人

如果想在類的方法內部調用其他方法時,我們也需要用到self來代表實例

 

 1 class Chinese:
 2 
 3     def greeting(self):
 4         print('很高興遇見你')
 5 
 6     def say(self):
 7         self.greeting() 
 8         print('我來自中國')
 9 
10 person = Chinese()  # 創建實例person
11 
12 person.say()  # 調用say()方法
13 很高興遇見你
14 我來自中國

self代表的是類的實例本身,方便數據的流轉
對此,我們需要記住兩點
第一點:只要在類中用def創建方法時,就必須把第一個參數位置留給 self,並在調用方法時忽略它(不用給self傳參)。
第二點:當在類的方法內部想調用類屬性或其他方法時,就要采用self.屬性名或self.方法名的格式。
##############################################################################################
二。特殊方法:初始化方法 (也叫構造函數)
定義初始化方法的格式是def __init__(self),是由init加左右兩邊的【雙】下划線組成
初始化方法的作用在於:當每個實例對象創建時,該方法內的代碼無須調用就會自動運行。

 

1 class Chinese:
2 
3     def __init__(self): 
4         print('很高興遇見你,我是初始化方法')
5 
6 person = Chinese()
7 很高興遇見你,我是初始化方法

編寫習慣上,我們會在初始化方法內部完成類屬性的創建,為類屬性設置初始值,
這樣類中的其他方法就能直接、隨時調用

 

 1 class Chinese:
 2     def __init__ (self):
 3         self.mouth = 1  # self.不能丟
 4         self.eye = 2
 5     
 6     def body(self):
 7         print('我有%s張嘴巴' % self.mouth)
 8         print('我有%s只眼睛' % self.eye)
 9 
10 person = Chinese()
11 person.body()
12 我有1張嘴巴
13 我有2只眼睛

 

 

除了設置固定常量,初始化方法同樣可以接收其他參數

 

 1 class Chinese:
 2 
 3     def __init__(self, name, birth, region):
 4         self.name = name   # self.name = '吳' 
 5         self.birth = birth  # self.birth = '廣東'
 6         self.region = region  # self.region = '深圳'
 7 
 8     def born(self):
 9         print(self.name + '出生在' + self.birth)
10 
11     def live(self):
12         print(self.name + '居住在' + self.region)    
13 
14 person = Chinese('吳','廣東','深圳') # 傳入初始化方法的參數
15 #初始化方法有多個參數的時候,在實例化的時候就要傳入相應的值
16 person.born()
17 person.live()
18 吳出生在廣東
19 吳居住在深圳

 

#其實還可以不用初始化方法也能實現
但是此方法比不上初始化方法
初始化優點:
至少不必重復傳參,傳入的數據還可以被多次調用

 

 1 class Chinese:
 2 
 3     def born(self, name, birthplace):
 4         print(name + '出生在' + birthplace)
 5 
 6     def live(self, name, region):
 7         print(name + '居住在' + region)   #不建議用此方法
 8 
 9 person = Chinese()
10 person.born('','廣東')
11 person.live('','深圳')

一次性調用

 1 class Chinese:
 2     def __init__(self,hometown,region):
 3         self.hometown = hometown
 4         self.region = region
 5         print('程序持續更新中……')
 6 
 7     def born(self):
 8         print('我生在%s。'%(self.hometown))
 9 
10     def live(self):
11         print('我在%s。'%(self.region))
12     
13     # 新建方法,調用上面的兩個方法(注:方法名可自定義)。
14     def citys(self):
15         self.born()
16         self.live()
17 
18 wu = Chinese('廣東', '深圳')
19 wu.citys()
20 # 調用方法后,程序運行方法中的代碼(即依次調用方法`born`和`live`)。
21 程序持續更新中……
22 我生在廣東。
23 我在深圳。

#####################################################################################################

面向對象編程
與面向對象編程相對應的是面向過程編程

面向過程編程:首先分析出解決問題所需要的步驟(即“第一步做什么,第二步做什么,第三步做什么”),
然后用函數實現各個步驟,再依次調用。

面向對象編程,將代碼具體的數據和處理方法都封裝在類中,讓我們不用完全了解過程也可以調用類中的各種方法。
這個優勢讓我們可以在 Python 中輕松地調用各種標准庫、第三方庫和自定義模塊(可以簡單理解成別人寫好的類)

#類編寫一個直觀的好處就是參數的傳遞會比普通函數要省事很多,也不必考慮全局變量和局部變量,因為類中的方法可以直接調用屬性。
#####################################################################################################################
綜合例子

 

 1 class Robot:
 2     def __init__(self):
 3         self.name = input('我現在剛誕生,還沒有名字,幫我起一個吧。')
 4         self.master = input('對了,我要怎么稱呼你呢?')
 5         print('你好%s,我叫%s。很開心,遇見你~'%(self.master,self.name))
 6     
 7     def say_wish(self):
 8         wish = input('告訴我一個你的願望吧:')
 9         print(self.master+'的願望是:')
10         # 這里也可以用字符串的格式化,不過,用循環語句的話,之后改復述次數會方便些。
11         for i in range(3):
12             print(wish)
13 
14 robot1 = Robot()
15 robot1.say_wish()

 

#############################################################################################################################
類的繼承和定制
A類屬於B類,自然也擁有了B類的所有屬性和方法。
這句話在編程里就是:A類繼承了B類。

Python中,我們的習慣表述是:A類是B類的子類,而B類是A類的父類(或超類)

 

定制
子類也可以在繼承的基礎上進行個性化的定制
(1)創建新屬性、新方法;

(2)修改繼承到的屬性或方法。

————————————————————————————————————————————
繼承的基礎語法

class Chinese:在運行時相當於class Chinese(object):。

而object,是所有類的父類,我們將其稱為根類(可理解為類的始祖)。

1 #函數isinstance(),判斷某個實例是否屬於某個類
2 print(isinstance(1,int))   ## 判斷1是否為整數類的實例
3 True
4 print(isinstance(1,str))
5 False
6 print(isinstance(1,(int,str))) # 判斷實例是否屬於元組里幾個類中的一個
7 True
 1 class Chinese:
 2     pass
 3 
 4 class Cantonese(Chinese):
 5     pass
 6 
 7 gonger = Chinese()
 8 yewen = Cantonese()
 9 
10 print('\n驗證1:子類創建的實例同時也屬於父類')
11 print(isinstance(gonger,Chinese))  
12 print(isinstance(yewen,Chinese))  
13 
14 print('\n驗證2:父類創建的實例不屬於子類。')
15 print(isinstance(gonger,Cantonese))
16 
17 print('\n驗證3:類創建的實例都屬於根類。')
18 print(isinstance(gonger,object))  
19 print(isinstance(yewen,object))
20 
21 驗證1:子類創建的實例同時也屬於父類
22 True
23 True
24 
25 驗證2:父類創建的實例不屬於子類。
26 False
27 
28 驗證3:類創建的實例都屬於根類。
29 True
30 True

————————————————————————————————————————————
類的繼承之多層繼承

子類創建的實例可調用所有層級父類的屬性和方法

 

 

 1 class Earthman:
 2     eye_number = 2
 3 
 4 # 中國人繼承了地球人
 5 class Chinese(Earthman):
 6     eye_color = 'black'
 7 
 8 # 廣東人繼承了中國人,同時也繼承了地球人。
 9 class Cantonese(Chinese):
10     pass
11 
12 yewen = Cantonese()
13 print(yewen.eye_number)
14 print(yewen.eye_color)
15 2
16 black

 

####################################################################
類的繼承之多重繼承

一個類,可以同時繼承多個類,
語法為 class A(B,C,D):

就近原則:
越靠近子類(即越靠左)的父類,越親近,越優先考慮。子類調用屬性和方法時,會先在靠左的父類里找,找不到才往右找。

 

 1 class Su:
 2     born_city = 'Jiangsu'
 3     wearing = 'thick'
 4 
 5     def diet(self):
 6         print('我們愛吃甜。')
 7 
 8 class Yue:
 9     settle_city = 'Guangdong'
10     wearing = 'thin'
11 
12     def diet(self):
13         print('我們吃得清淡。')
14 
15 class Yuesu(Yue,Su):  
16     pass
17 
18 xiaoming = Yuesu()
19 print(xiaoming.wearing) # 先在 Yue類找,找到了,打印出來。
20 print(xiaoming.born_city) # Yue類沒有born_city,才去Su類找。
21 xiaoming.diet() # 方法調用,和屬性調用一樣,也符合就近原則。
22 
23 thin
24 Jiangsu
25 我們吃得清淡。

 

類的定制
定制,可以新增代碼

 

 1 class Chinese:
 2     eye = 'black'
 3 
 4     def eat(self):
 5         print('吃飯,選擇用筷子。')
 6 
 7 class Cantonese(Chinese):  # 類的繼承
 8     native_place = 'guangdong'  # 類的定制
 9 
10     def dialect(self):  # 類的定制
11         print('我們會講廣東話。')
12 
13 yewen = Cantonese()
14 print(yewen.eye)           # 父類的屬性能用
15 print(yewen.native_place)  # 子類的定制屬性也能用
16 yewen.eat()                # 父類的方法能用
17 yewen.dialect()            # 子類的定制方法也能用
18 
19 black
20 guangdong
21 吃飯,選擇用筷子。
22 我們會講廣東話。

定制,也可重寫代碼
在子類中,對父類代碼的修改

子類繼承父類方法的操作是在def語句后接父類.方法(參數)

 

 

 1 class Chinese:
 2 
 3     def land_area(self,area):
 4         print('我們居住的地方,陸地面積是%d萬平方公里左右。'% area)
 5 
 6 class Cantonese(Chinese):
 7     # 間接對方法進行重寫
 8     def land_area(self, area, rate = 0.0188):
 9         Chinese.land_area(self, area * rate)
10         # 直接繼承父類方法,再調整參數。
11 
12 gonger = Chinese()
13 yewen = Cantonese()
14 gonger.land_area(960)
15 yewen.land_area(960)

 

提示:初始化方法的定制,和一般的實例方法的定制是一樣的。

 

 1 class Chinese:
 2     def __init__(self, greeting='你好', place='中國'):
 3         self.greeting = greeting
 4         self.place = place
 5 
 6     def greet(self):
 7         print('%s!歡迎來到%s。' % (self.greeting, self.place))   
 8 
 9 # 請為子類完成定制,代碼量:兩行。
10 class Cantonese(Chinese):
11     def __init__(self, greeting='雷猴', place='廣東'):  #重寫代碼最好是在繼承方法的基礎上通過代碼的調整完成定制
12         Chinese.__init__(self, greeting ,place)   
13    
14 yewen = Cantonese()
15 yewen.greet()
16 雷猴!歡迎來到廣東。

 

###################################################################################################################
列子

 1 class Student:
 2     def __init__(self, name, job=None, time=0.00, time_effective=0.00): 
 3         self.name = name
 4         self.job = job
 5         self.time = time
 6         self.time_effective = time_effective
 7 
 8     def count_time(self, hour, rate):
 9         self.time += hour
10         self.time_effective += hour * rate
11 
12 class Programmer(Student):
13     def __init__(self, name): #此處為啥只留name參數,因為沒有給出默認值,需要傳入參數,不能省略,然后其他都是默認參數
14         Student.__init__(self, name, job='programmer', time=0.00, time_effective=0.00)
15 
16     def count_time(self, hour, rate=1):
17         Student.count_time(self, hour, rate)
18 
19 student1 = Student('韓梅梅')
20 student2 = Programmer('李雷')
21 
22 print(student1.job)
23 print(student2.job)
24 
25 student1.count_time(10, 0.8)
26 student2.count_time(10)
27 
28 print(student1.time_effective)
29 print(student2.time_effective)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM