python面向對象中類對象、實例對象、類變量、實例變量、類方法、實例方法、靜態方法
1. 類對象和實例對象
Python
中一切皆對象,Python類本身也是一種對象,類定義完成後,會在當前作用域中定義一個以類名為名字的命名空間。類對象具有以下兩種操作:
- 可以通過“類名()”的方式實例化一個對象。
- 可以通過“類名.類屬性”的方式來訪問一個類屬性。
如果說類時一種概念性的定義,是一種類別,那麽實例對象就是對這一類別的具體化、實例化,即實例化對象是類對象實例化之後的產物。
class Person:# 聲明一個類對象 pass p1 = Person()#聲明一個實例對象 print(Person)#輸出結果:<class ‘__main__.Person‘>print(p1)#<__main__.Person object at 0x0000015F7F94D0F0>
2 類變量與實例變量
2.1 概念上的區別
類變量是指是指該類的所有實例說共有的數據,實例變量是該類每一個實例所特有的數據。這麽說的話可能還是很抽象,我們拿人類(Person類)來打比方,人類能移動(move=True),這是每一個人(張三、李四)都能做的,所以我們可以說人類能移動,張三能移動,李四也能移動,這裏的移動(move)就是一個類變量。但每一個人都可能有不同的姓名(name)和年齡(age),張三可能20歲,李四可能30歲,但是我們不能說人類(Person)都是20歲或30歲,這裏的姓名(name)和年齡(age)就是實例變量。
class Person: move = True # 這是類變量 def __init__(self , name , age): self.name = name # 這是實例變量 self.age = age # 這是實例變量
2.2 聲明上的區別
類變量聲明通常在類內部,但函數體外,不需要用任何關鍵字修飾。實例變量一般聲明在實例方法內部(其他方法內部也不行),且用self關鍵字修飾。
class Person: move = True # 這是類變量, def __init__(self , name): self.name= name # 這是實例變量,必須聲明在實例函數內,用self關鍵字修飾 # move = True # 類變量不能再函數體內聲明,在這個位置聲明的又沒有self關鍵字修飾,只能是一個局部變量 # self.age = age # 這是錯誤的,實例變量不能再這裏聲明 eat = True # 這是類變量,可以在函數體外,類內部任意位置
上面的變量綁定都是在對象聲明過程中綁定的,但事實上類變量和實例變量都可以在類或者實例都可以在對象聲明結束之後再綁定。“類名.變量名”綁定的是類變量,“實例名.變量名”綁定的是實例變量。
class Person: move = True def __init__(self , name , age): self.name = name self.age = age p1 = Person(‘張三‘ , 20) p1.gender=‘男‘ # 聲明實例對象結束之後再綁定一個實例變量 Person.eat = True # 聲明類對象結束之後再綁定一個類變量 print(p1.gender) # 輸出結果:男 print(p1.eat) #輸出結果:True
註:雖然可以在對象聲明之後再綁定對象,但是這種方式最好不要使用。
2.3 訪問上的區別
類變量可以通過“類名.變量名”和“實例名.變量名”的方式訪問。實例變量只能通過“實例名.變量名”的方式來訪問。
class Person: move = True # 這是類變量 def __init__(self , name , age): self.name = name # 這是實例變量 self.age = age # 這是實例變量 p1 = Person(‘張三‘ , 20) print(p1.name , p1.age) # 通過“實例名.變量名”的方式訪問實例變量 print(p1.move) # 通過“實例名.變量名”的方式訪問實例變量 print(Person.move) # 通過“類名.變量名”方式訪問類變量 # print(Person.name) # 這是錯誤的
註:雖然可以通過“實例名.類變量名”的方式訪問類變量,但是並不推薦,最好還是通過“類名.類變量名”來訪問類變量。
2.4 存儲上的區別
類變量只會在用class關鍵字聲明一個類時創建,且也只會保存在類的命名空間中,這個類的實例的命名空間中是沒有的。通過“實例名.類變量名”訪問類變量時,實際訪問的是類命名空間中數據,所以所有實例訪問到的數據都是同一個變量。實例變量保存在實例各自的命名空間中。
class Person: move = True # 這是類變量 def __init__(self , name , age): self.name = name # 這是實例變量 self.age = age # 這是實例變量 p1 = Person(‘張三‘ , 20) p2 = Person(‘李四‘ , 30) # 通過id()函數查詢move內存地址 print(id(p1.move)) # 輸出結果為:1622667424 print(id(p1.move)) # 輸出結果為:1622667424
3 靜態方法、類方法、實例方法
3.1 靜態方法
靜態方法是指在定義時,使用@staticmethod裝飾器來修飾,無序傳入self或cls關鍵字即可進行創建的方法。在調用過程時,無需將類實例化,直接通過“類名.方法名()”方式調用方法。當然,也可以在實例化後通過“實例名.方法名()”的方式調用。在靜態方法內部,只能通過“類名.類變量名”的方式訪問類變量。
class Person: move = True def __init__(self , name , age): self.name = name self.age = age @staticmethod def static_fun(): # 聲明一個靜態方法 print(Person.move) p1 = Person(‘張三‘ , 20) p1.static_fun() #輸出結果:這是靜態方法 Person.static_fun() #輸出結果:這是靜態方法
3.2 類方法
類方法需要使用@classmethod裝飾器來修飾,且傳入的第一個參數為cls,指代的是類本身。類方法在調用方式上與靜態方法相似,即可以通過“類名.方法名()”和“實例名.方法名()”兩種方式調用。但類方法與靜態方法不同的是,類方法可以在方法內部通過cls關鍵字訪問類變量。在類方法內部,既能通過“類名.類變量名”的方式訪問類變量,也能通過“cls.類變量名”的方式訪問類變量。
class Person: move = True def __init__(self , name , age): self.name = name self.age = age @classmethod def class_fun(cls): # 聲明一個類方法 print(cls.move) print(Person.move)# cls 指的就是Person類,等效 p1 = Person(‘張三‘ , 20) p1.class_fun() #輸出結果:True True Person.class_fun() #輸出結果:True True
3.3 實例方法
在一個類中,除了靜態方法和類方法之外,就是實例方法了,實例方法不需要裝飾器修飾,不過在聲明時傳入的第一個參數必須為self,self指代的就是實例本身。實例方法能訪問實例變量,靜態方法和類方法則不能。在實例方法內部只能通過“類名.類變量名”的方式訪問類變量。在調用時,實例方法可以通過“實例名.實例方法名”來調用,如果要通過類來調用,必須必須顯式地將實例當做參數傳入。
class Person: move = True def __init__(self , name , age): self.name = name self.age = age def instance_fun(self): # 聲明一個實例方法 print(Person.move) # 訪問類變量 print(self.name , self.age) p1 = Person(‘張三‘ , 20) p1.instance_fun() Person.instance_fun(p1) #通過類訪問實例方法時,必須顯式地將實例當做參數傳入
python面向對象中類對象、實例對象、類變量、實例變量、類方法、實例方法、靜態方法