文章目錄
面向對象
定義類
語法:
class 類名:
類中成員
類中的成員:實例屬性,實例方法,類屬性,類方法,靜態方法等
下面會把類中的成員全部單獨說明,代碼都是獨立的,爲了方便理解!
定義一個類並創建類實例
# 定義一個類,使用class關鍵字
class Student:
pass # 暫時不賦值
#創建類的對象
stu1 = Student() # 創建Student類的一個實例
stu2 = Student()
print(stu1,'自定義類型type:',type(stu1))
print(stu2,'自定義類型type:',type(stu2))
# 測試,對比type類型
a = 666
print(a,'默認type:',type(a))
c = '六六六'
print(c,'默認type:',type(c))
print('*' * 59)
爲對象綁定實例屬性
# 定義一個類,使用class關鍵字
class Student:
pass # 暫時不賦值
#創建類的對象
stu1 = Student() # 創建Student類的一個實例
stu2 = Student()
print(stu1,'自定義類型type:',type(stu1))
print(stu2,'自定義類型type:',type(stu2))
# 爲對象綁定屬性 (注:需要先給類創建實例)
stu1.name = 'ccx'
stu1.age = 22
stu2.name = 'xgq'
stu2.age = 23
stu2.sex = 'woman'
print('stu1的參數:',stu1.name,stu1.age) #打印stu1的參數
print('stu2的參數:',stu2.name,stu2.sex,stu2.age) # 打印stu2的參數
創建實例方法以及使用實例方法
- 下面這方法是默認不傳參的方法
# 定義一個類,使用class關鍵字
class Student:
#pass # 暫時不賦值
# 創建實例方法:將self作爲第一個參數的方法 (self自動生成)
def say_hi(self): # self表示當前類的實例,類似於java中的this
print('Hi ' + self.name) # 傳入name參數。
#創建類的對象
stu1 = Student() # 創建Student類的一個實例
stu2 = Student()
#print(stu1,'自定義類型type:',type(stu1))
#print(stu2,'自定義類型type:',type(stu2))
# 爲對象綁定屬性 (注:需要先給類創建實例)
stu1.name = 'ccx'
stu1.age = 22
stu2.name = 'xgq'
stu2.age = 23
stu2.sex = 'woman'
# print('stu1的參數:',stu1.name,stu1.age) #打印stu1的參數
# print('stu2的參數:',stu2.name,stu2.sex,stu2.age) # 打印stu2的參數
#訪問實例方法
stu1.say_hi() # 調用方法時無需傳遞self,由解析器調用時將對象作爲self自動傳入
stu2.say_hi()
- 下面說一下傳參的方法
# 定義一個類,使用class關鍵字
class Student:
#pass # 暫時不賦值
# 創建實例方法:將self作爲第一個參數的方法 (self自動生成)
def say_hi(self): # self表示當前類的實例,類似於java中的this
print('Hi ' + self.name) # 傳入name參數。
# 創建一個需要傳參數的方法
def say_hello(self,username='默認是hero'): #定義了默認值
print('hello ',username)
#創建類的對象
stu1 = Student() # 創建Student類的一個實例
stu2 = Student()
# 爲對象綁定屬性 (注:需要先給類創建實例)
stu1.name = 'ccx'
stu2.name = 'xgq'
# 調用不需要傳參的方法
stu1.say_hi()
stu2.say_hi()
#調用傳參的方法
stu1.say_hello() # 不傳參也不會報錯
stu2.say_hello('崔') # 傳參
類屬性
# 定義一個類,使用class關鍵字
class Student:
# 類屬性:直接在類中定義的屬性,可以通過類或者實例對象來訪問
boy = 'good enveving '
stu1 = Student() # 創建一個類對象
stu2 = Student()
# 訪問類屬性
print(Student.boy)
stu1.boy = '晚上好' #stu1添加了一個實例屬性,並不會改變類屬性中boy的值
print(stu1.boy)
print(stu2.boy) # 如果當前實例沒有boy屬性,則會向上查找類屬性boy
類方法
# 定義一個類,使用class關鍵字
class Student:
# 類屬性:直接在類中定義的屬性,可以通過類或者實例對象來訪問
boy = 'good enveving '
#類方法:使用@classmethod修飾的方法,將cls作爲第一個參數
@classmethod
def show(cls, msg): # cls是默認生成的,表示當前類,msg是自定義傳參值
print(msg,cls.boy)
stu1 = Student() # 創建一個類對象
stu2 = Student()
# 訪問類屬性
# print(Student.boy)
# stu1.boy = '晚上好' #stu1添加了一個實例屬性,並不會改變類屬性中boy的值
# print(stu1.boy)
# print(stu2.boy) # 如果當前實例沒有boy屬性,則會向上查找類屬性boy
#調用類方法
# 通過類調用
Student.show('ccx') #調用方法時候無需傳遞cls,但定義了msg,所以需要傳入一個參數
# 通過對象調用
stu1.show('xgq')
靜態類方法
# 定義一個類,使用class關鍵字
class Student:
# 類屬性:直接在類中定義的屬性,可以通過類或者實例對象來訪問
boy = 'good enveving '
#類方法:使用@classmethod修飾的方法,將cls作爲第一個參數
@classmethod
def show(cls, msg): # cls是默認生成的,表示當前類,msg是自定義傳參值
print(msg,cls.boy)
# 靜態方法:使用@staticmethod修飾的方法,沒有任何必選參數,不需要講cls作爲第一參數
@staticmethod
def show2(msg): # msg也可以不要
print(msg,Student.boy) #因爲沒有cls表示類,要調用類中屬性,可以直接類名.屬性即可
stu1 = Student() # 創建一個類對象
stu2 = Student()
#調用類方法
# 通過類調用
Student.show('ccx') #調用方法時候無需傳遞cls,但定義了msg,所以需要傳入一個參數
# 通過對象調用
stu1.show('xgq')
print('*' * 50)
# 調用靜態類方法
Student.show2('崔崇鑫') # 通過類調用
stu1.show2('xgq') # 通過對象調用
構造方法
# 下面__是兩個下劃線
__int__() :構造方法,在創建對象時會自動調用
class Student:
#構造方法(函數),不支持重載
def __init__(self,name,age): #self是自動生成(當前類),name和age是自定義需要初始化的值
print('創建對象,執行構造方法。。。')
self.newname = name # 初始化值,必須初始化!!!!!
self.newage = age
# 實例方法
def show(self):
print(self.newname,self.newage)
print('mr %s ,年齡 %d' % (self.newname,self.newage))
# 調用構造方法
stu1 = Student('ccx',22) #創建對象並傳入2個參數
print(stu1.newname,stu1.newage) #輸出
print('*' * 50)
#調用實例方法
stu1.show()
封裝
封裝:隱藏對象中一些不希望被外部所訪問到的屬性,保證數據的安全。
一般定義方法:缺乏隱蔽性,數據不安全
class Student:
pass
stu1 = Student()
stu1.num = 50
print(stu1.num)
封裝方法 :外界看不到數據,更安全
class Student:
# 定義私有屬性
__num = 50 # 以兩個下劃線開頭,表示對象的隱藏屬性,只能在類內部訪問
# 提供getter/setter方法
def get_num(self):
return self.__num # 返回該類的值是定義的__num值
# 可以更改__num的值
def set_num(self, num):
# 比如你只想輸入的值在1-100之間,否則就是默認值
if 0 < num < 101:
self.__num = num # num是傳入的參數
return self.__num
else:
self.__num = 50
return self.__num
stu1 = Student() # 創建對象
# 調用封裝的值
# print((stu1.__num)) # 外類外部無法訪問私有屬性
print('普通調用:',stu1.get_num()) # 調用普通返回類的值
print('輸入66:',stu1.set_num(66))
print('輸入666:',stu1.set_num(666))
繼承
繼承:使一個類能夠獲取到其他類中的屬性和方法
父類:其實就是一個普通class name(object)
,父類中object
可以省略,所以平常就直接 class name
即可
子類繼承父類:class name
(父類name)
定義父類,子類繼承父類的使用
#定義一個Person類,父類(超類,基類)
class Person:
def __init__(self,name): # 定義私有類
self.name = name
def run(self):#定義一個類函數
print('person:'+ self.name+'正在奔跑啊啊啊')
class Student(Person): #繼承自Person
def __init__(self,name,set,age):# 定義私有類
#調用父類的構造方法
# Person.__init__(name) # 方式一:直接指定父類的構造方法
super().__init__(name)# 方式二:使用super(),推薦使用該方法
# 自己類中的構造方法且父類中沒有的,直接定義即可
self.set = set
self.age = age
def study(self): #定義一個類函數
print('stadent:' + self.name + '正在學習。。。。')
def show(self):#定義一個類函數
print('name:%s , set:%s,age:%s'%(self.name,self.set,self.age))
#可以自定義n個類函數 。。。
stu = Student('ccx','man',22)
stu.run() #因爲繼承了父類,當然也可以直接調用父類函數
stu.study()
stu.show()
子類重寫父類
其實就是在子類中重新編輯一個和父類方法名一摸一樣的就可以覆蓋父類中的方法內容了,super().父類方法名()
就是調用父類方法內容,如果不要該行,則父類方法中內容全部失效。然後在子類方法中定義新的內容。打印該方法 顯示的內容就是子類方法內容了。
#定義一個Person類,父類(超類,基類)
class Person:
def __init__(self,name): # 定義私有類
self.name = name
def run(self):#定義一個類函數
print('person:'+ self.name+'正在奔跑啊啊啊')
class Student(Person): #繼承自Person
def __init__(self,name,set,age):# 定義私有類
#調用父類的構造方法
# Person.__init__(name) # 方式一:直接指定父類的構造方法
super().__init__(name)# 方式二:使用super(),推薦使用該方法
# 自己類中的構造方法且父類中沒有的,直接定義即可
self.set = set
self.age = age
def study(self): #定義一個類函數
print('stadent:' + self.name + '正在學習。。。。')
def show(self):#定義一個類函數
print('name:%s , set:%s,age:%s'%(self.name,self.set,self.age))
#可以自定義n個類函數 。。。
# 重寫父類的方法
def run(self):
#super().run() #調用父類的方法 ,如果不要該行,那麼父類中的該方法內容就不會輸出了
print('new person :'+ self.name+'正在奔跑咯') #新定義方法內容
stu = Student('ccx','man',22)
stu.run() #因爲繼承了父類,當然也可以直接調用父類函數
stu.study()
stu.show()
常用的條件判斷
#定義一個Person類,父類(超類,基類)
class Person:
def __init__(self,name): # 定義私有類
self.name = name
def run(self):#定義一個類函數
print('person:'+ self.name+'正在奔跑啊啊啊')
class Student(Person): #繼承自Person
def __init__(self,name,set,age):# 定義私有類
#調用父類的構造方法
# Person.__init__(name) # 方式一:直接指定父類的構造方法
super().__init__(name)# 方式二:使用super(),推薦使用該方法
# 自己類中的構造方法且父類中沒有的,直接定義即可
self.set = set
self.age = age
def study(self): #定義一個類函數
print('stadent:' + self.name + '正在學習。。。。')
def show(self):#定義一個類函數
print('name:%s , set:%s,age:%s'%(self.name,self.set,self.age))
#可以自定義n個類函數 。。。
# 重寫父類的方法
def run(self):
#super().run() #調用父類的方法 ,如果不要該行,那麼父類中的該方法內容就不會輸出了
print('new person :'+ self.name+'正在奔跑咯') #新定義方法內容
stu = Student('ccx','man',22)
stu.run() #因爲繼承了父類,當然也可以直接調用父類函數
stu.study()
stu.show()
#判斷一個對象是否指定類的實例,即判斷對象的類型
print(isinstance(stu,Student))
print(isinstance(stu,Person))
# 判斷一個類是否是指定類的子類
print(isinstance(Student,Person))
print(isinstance(Person,object))
# object類是所有類的根類,默認所有類都繼承自object
print(stu.__doc__) # 輸出文件開頭註釋的內容(""""""),如果沒註釋,就是None
print(stu.__dict__) # 以字典的形式打印stu的值
多繼承
多繼承: 顧名思義,就是說一個類可以繼承多個父類,多個父類之間用逗號隔開就好。
注:不建議使用多繼承,因爲如果 父類A和父類B中方法有一樣的,會存在覆蓋或存在加載順序的問題。
# 定義一個父類B
class A:
def a(self):
print('a')
# 定義一個父類B
class B:
def b(self):
print('b')
# 定義一個類並繼承多個父類,用逗號隔開(java中不支持繼承多類)
class C(A,B):
def c(self):
print('c')
stu = C()
stu.a()
stu.b()
stu.c()
# 類有一個特殊屬性 __bases__ 可以用來獲取當前類的所有父類
print(C.__bases__)
多態
多態:可以 以 多種不同形態展示!
class Animal: #定義一個動物類
def __init__(self,name):
self.name = name
def cry(self):
print('動物在叫啊。。。。')
class Dog(Animal) : # 定義一個類狗,並繼承動物類
def __init__(self,name,age):
super().__init__(name)
self.age = age
def cry(self):
print('狗在叫。。。汪汪汪')
class Cat(Animal) : # 定義一個類毛,並繼承動物類
def __init__(self,name,sex):
super().__init__(name)
self.sex = sex
def cry(self):
print('貓在叫。。。嗚哇嗚哇')
#一個對象可以以不同的形式去呈現,就是多態
def play(name): # 注意,這是以函數的方法 調用 上面類的
print(name.name) #以名字返回,只有一個name返回的是內存地址
name.cry() # 返回類中的 cry方法內容
# 創建對象
dog = Dog('大黃',2)
cat = Cat('喵咪','公')
play(dog)
play(cat)
魔術方法
什麼是Python魔法方法?
魔法方法就如同它的名字一樣神奇,總能在你需要的時候爲你提供某種方法來讓你的想法實現。魔法方法是指Python內部已經包含的,被雙下劃線所包圍的方法,這些方法在進行特定的操作時會自動被調用,它們是Python面向對象下智慧的結晶。初學者掌握Python的魔法方法也就變得尤爲重要了。
爲什麼要使用Python魔法方法?
使用Python的魔法方法可以使Python的自由度變得更高,當不需要重寫時魔法方法也可以在規定的默認情況下生效,在需要重寫時也可以讓使用者根據自己的需求來重寫部分方法來達到自己的期待。而且衆所周知Python是支持面向對象的語言Python的基本魔法方法就使得Python在面對對象方面做得更好。
魔法方法的一些語法
基礎魔法方法(較爲常用)
# 下面的__都是2個下劃線
__new__(cls[, ...]) 纔是實例化對象調用的第一個方法,它只取下 cls 參數,並把其他參數傳給 __init__。 __new__很少使用,但是也有它適合的場景(單例模式),尤其是當類繼承自一個像元組或者字符串這樣不經常改變的類型的時候。
__init__(self[, ...])構造方法,初始化類的時候被調用
__del__(self)析構方法,當實例化對象被徹底銷燬時被調用(實例化對象的所有指針都被銷燬時被調用)
__call__(self[, args...])允許一個類的實例像函數一樣被調用:x(a, b) 調用 x.__call__(a, b)
__len__(self)定義當被 len() 調用時的行爲__repr__(self)定義當被 repr() 調用時的行爲
__str__(self)定義當被 str() 調用時的行爲__bytes__(self)定義當被 bytes() 調用時的行爲
__hash__(self)定義當被 hash() 調用時的行爲
__bool__(self)定義當被 bool() 調用時的行爲,應該返回 True 或 False
__format__(self, format_spec)定義當被 format() 調用時的行爲
屬性相關的方法
# 下面的__都是兩個下劃線
__getattr__(self, name)定義當用戶試圖獲取一個不存在的屬性時的行爲
__getattribute__(self, name)定義當該類的屬性被訪問時的行爲
__setattr__(self, name, value)定義當一個屬性被設置時的行爲
__delattr__(self, name)定義當一個屬性被刪除時的行爲
__dir__(self)定義當 dir() 被調用時的行爲
__get__(self, instance, owner)定義當描述符的值被取得時的行爲
__set__(self, instance, value)定義當描述符的值被改變時的行爲
__delete__(self, instance)定義當描述符的值被刪除時的行爲
比較操作符
# 下面的__都是兩個下劃線
__lt__(self, other)定義小於號的行爲:x < y 調用 x.__lt__(y)
__le__(self, other)定義小於等於號的行爲:x <= y 調用 x.__le__(y)
__eq__(self, other)定義等於號的行爲:x == y 調用 x.__eq__(y)
__ne__(self, other)定義不等號的行爲:x != y 調用 x.__ne__(y)
__gt__(self, other)定義大於號的行爲:x > y 調用 x.__gt__(y)
__ge__(self, other)定義大於等於號的行爲:x >= y 調用 x.__ge__(y)
類型轉換
# 下面的__都是兩個下劃線
__complex__(self)定義當被 complex() 調用時的行爲(需要返回恰當的值)
__int__(self)定義當被 int() 調用時的行爲(需要返回恰當的值)
__float__(self)定義當被 float() 調用時的行爲(需要返回恰當的值)__round__(self[, n])定義當被 round() 調用時的行爲(需要返回恰當的值)
容器類型(一般用於操作容器類)
# 下面的__都是兩個下劃線
__len__(self)定義當被 len() 調用時的行爲(一般返回容器類的長度)
__getitem__(self, key)定義獲取容器中指定元素的行爲,相當於 self[key]
__setitem__(self, key, value)定義設置容器中指定元素的行爲,相當於 self[key] = value
__delitem__(self, key)定義刪除容器中指定元素的行爲,相當於 del self[key]
__iter__(self)定義當迭代容器中的元素的行爲
__reversed__(self)定義當被 reversed() 調用時的行爲
__contains__(self, item)定義當使用成員測試運算符(in 或 not in)時的行爲
特點:
1 都是以雙下劃線開頭,以雙下劃線結尾;
2 不需要手動調用,在特定的時機 會自動執行。
- 特點展示
# 定義一個類
class Person(object) : # object 可以不要,所有父類默認繼承object
def __init__(self,name,age):
print('__init__')
self.name = name
self.age = age
p1 = Person('崔崇鑫',22)
print(p1)
- 功能使用(部分)
這裏只展示部分功能使用,具體的可以參加上面提到的語法,使用方法都一樣。
# 定義一個類
class Person(object) : # object 可以不要,所有父類默認繼承object
def __init__(self,name,age):
print('__init__')
self.name = name
self.age = age
# 將對象轉換爲字符串時調用,類似於java中的toString()
def __str__(self): # 如果不轉換,則返回的是內存地址
return 'Person [name=%s,age=%d]' % (self.name,self.age)
# 在對象使用len()函數時調用
def __len__(self):
return len(self.name)
# 在對象使用repr()函數時調用
def __repr__(self):
return 'hello person'
p1 = Person('崔崇鑫',22)
print(p1)
print(len(p1))
print(repr(p1))