一、面向對象
程序 現實
對象——————>具體的事物
現實的事物——————>轉成電腦程序
世間萬物皆對象
優點:
提高代碼複用性
面向對象:
類、對象、屬性、方法
對象的集合
------> 類別
------> 共同的特徵 屬性
------> 動作 方法
多個對象 ————> 提取對象共同的特徵和動作 ————> 封裝到一個類中
#所有類名,要求首字母大寫,多個單詞使用駝峯式命名
'''
繼承
class 類名[(父類)]:
屬性 特徵
方法 動作
'''
class Phone:
#屬性
brand = 'huawei'
#方法
#使用類 創建對象
p = Phone()
print(p)
print(p.brand)
#定義類和屬性
class Student:
#類屬性
name = 'aaa'
age = '2'
#先找自己空間的,再去模型中找,如果自己空間中存在age屬性,不會去模型類中查找
#使用類,創建對象
tom = Student()
#對象屬性 動態創建屬性,屬於自己
tom.name = 'tom'
tom.age = 18
print(tom.name)
lucy = Student()
lucy.name = 'lucy'
lucy.age = 30
print(lucy.name)
#修改Student類中的屬性值
Student.name = 'bbb'
二、方法
類中方法:動作
種類: 普通方法 類方法 靜態方法 魔術方法
普通方法格式:
def 方法名(self[,參數, 參數])
類方法: 裝飾器@classmethod 調用方法:類名.類方法()
不依賴於對象,可以獨立對象
特點:
1、定義需要依賴裝飾器@classmethod
2、類方法中的參數不是一個對象,而是當前類
3、類方法中只可以使用類屬性
4、類方法中不能使用普通方法,方法中有self,方法依賴self,而類方法無法傳遞self參數
格式:
@classmethod
def 方法名(cls):
pass
類方法的作用:
因爲只能訪問類屬性和類方法,所以可以在對象創建之前,如果需要完成一些動作(功能)
靜態方法: 類似於類方法
1、需要裝飾器@staticmethod
2、靜態方法是無需傳遞參數cls或self
3、也只能訪問類的屬性和方法,無法訪問對象的屬性和方法
4、加載時機同類方法
格式:
@staticmethod
def 方法名():
pass
總結:類方法 和 靜態方法
不同:
1、裝飾器不同歐冠
2、類方法是有參數的,靜態方法沒有參數
相同:
1、只能訪問類的屬性和方法,對象的屬性和方法無法訪問
2、都可以通過類名調用訪問
3、都可以在創建對象之前使用,因爲是不依賴於對象的
普通方法 與 類方法和靜態方法的區別:
不同:
1、沒有裝飾器
2、普通方法永遠是要依賴對象,因爲每個普通方法都有一個self self爲對象本身
3、只有創建了對象纔可以調用普通方法,否則無法調用
魔術方法:
__init__: 初始化魔術方法 執行__new__()後,接受到__new__()方法返回的地址,並給對象賦值地址,再執行__init__()方法
觸發時機:初始化對象時觸發(不是實例化觸發,但是和實例化在一個操作中)
__new__:實例化的魔術方法 先執行__new__(),向內存申請空間,並返回開闢的地址
觸發時機:在實例化對時觸發
__call__:調用對象的魔術方法
觸發時機:將對象當作函數調用時觸發 對象()
會默認調用此函數中的內容
__del__: delete縮寫 析構魔術方法
觸發時機:當對象沒有用(沒有任何變量引用)的時候被觸發
1、對象賦值
tp = TestPhone()
tp1 = tp 說明:tp和tp1共同指向同一個地址
2、刪除地址的引用
del p1 刪除p1對地址的引用
3、查看對地址的引用次數
import sys
sys.getrefcount(tp)
4、當一塊空間沒有任何引用(地址指向),默認執行__del__()
當執行代碼最後, python解釋器,回收所有在本次執行過程中使用到的空間
垃圾回收機制:python底層自帶,內存釋放
__str__:單純打印對象名稱
觸發時機:打印對象名,自動觸發調用__str__裏面的內容
print(對象)
注意:一定要在__str__方法中添加return,return後面的內容就是打印對象看到的內容
總結:魔術方法
重點:
__init__ 構造方法,創建完空間之後調用的第一個方法
__str__ 打印對象的名稱
瞭解:
__new__ 作用:開闢空間
__del__ 作用:沒有指針引用的時候會調用,99%都不需要重寫
__call__ 作用:是否將對象當成函數用
總結:
方法:
普通方法
def 方法名(self, 參數...):
pass
對象.普通方法()
方法之間的調用:
class A:
def a(self):
pass
def b(self):
#調用a方法
self.a()
類方法:
@classmethod
def 方法名(cls, 參數...):
pass
類名.方法名()
對象.方法名()
靜態方法:
@staticmethod
def 方法名(參數...):
pass
類名.方法名()
對象.方法名()
魔術方法:
自動執行的方法
print(對象) ---> __str__
代碼部分:
import sys
class TestPhone:
#函數 和 類裏面定義的 方法
__size = 20 #私有變量
brand = "info"
#魔術方法之一
#init 初始化
def __init__(self, brand): #獲取new中的地址,給對象賦值地址
print("------> init", self)
self.brand = brand
# self.price = price
# self.p_type = 'mate 30'
#向內存要空間 -->地址
def __new__(cls, brand): #*args, **kwargs #先執行new方法,new新開闢空間(開闢內存)
print("------> new")
position = object.__new__(cls) #申請內存開闢空間,獲取開闢的地址
print(position)
return position #地址
#調用方式: 對象()
def __call__(self, *args, **kwargs):
print("------> call ")
print("執行對象得到參數是:", args) #輸出:('aaa',)
#單純打印對象名稱,出來的是地址。地址對於開發者來說沒有太大意義
#如果想在打印對象名的時候,能夠給開發者更多的信息量,
def __str__(self):
print("------> str")
return self.brand #此時對象名稱爲 brand屬性的名稱
#del 對象
def __del__(self):
print("------> delete")
# def cus_call(self): #self是不斷髮生改變
# print("價格", self.price) #不能保證每個self中都存在price
#類裏面的方法 依賴於對象,self爲對象的地址
def call(self): #自己
print('self--->', self)
#類方法 傳的參數不是對象,是類 cls-->對應TestPhone類
@classmethod
def test(cls):
print(cls) #<class '__main__.TestPhone'>
# print(cls.brand) 報錯
@classmethod
def update_size(cls):
__size = 50
print("尺寸爲:", __size)
def obj_test(self):
print("object info method")
self.test() #類中方法的調用,需要self.方法名
@staticmethod
def s_test():
print("------> 靜態方法")
# print(self.brand) #語法錯誤
print(TestPhone.__size)
# tp = TestPhone('huawei', 5999)
# tp.cus_call()
# tp2 = TestPhone('xiaomi', 3999)
# tp2.cus_call()
# tp2.test()
#調用類方法
TestPhone.update_size()
#調用靜態方法
TestPhone.s_test()
tp = TestPhone('huawei')
print(tp.brand)
tp('aaa')
tp.brand = 'test'
tp1 = tp
print(tp1.brand)
tp2 = tp
print(tp2.brand)
print("*" * 20)
print(tp) #調用__str__
print("--->", tp.brand)
#斷掉tp1、tp2的引用
del tp1
del tp2
print(sys.getrefcount(tp)) #獲取對象的引用個數,調用這個函數也算一個