python _ 面向物件中類及其屬性方法
阿新 • • 發佈:2019-01-28
一、面向物件中的內建方法
1、del方法:
在python中
當使用類名()建立物件時,為物件分配完空間後,會自動呼叫__init__方法
當一個物件被從記憶體中銷燬前,會自動呼叫__del__方法,這裡是兩個下劃線del再接著兩個下劃線
2、del案例:
class Cat():
def __init__(self,new_name):
self.name = new_name
print '%s來了'%self.name
def __del__(self):
print '%s走了'%self.name
tom = Cat('tom' )
print tom.name
del tom #加上del tom分割線就會在最後面列印
# 物件被從記憶體中銷燬前,會自動呼叫__del__方法,所以先輸出tom走了
print '-' * 50
3、str方法:
在python中,使用python輸出物件變數
預設情況下,會輸出這個變數引用的物件是由哪一個類建立的物件
以及在記憶體中的地址(十六進位制表示)
如果在開發中,需要使用print輸出物件變數時
能夠列印自定義的內容,就能使用__str__這個內建方法了
4、str案例:
class Cat():
def __init__(self,name):
self.name = name
def __str__(self):
return '我是%s'% self.name
tom = Cat('tom')
print tom
二、私有屬性和私有方法
應用場景及定義方式
應用場景:
在實際開發中,物件的某些屬性或方法只希望在物件內部使用,
而不希望在物件外部使用
私有屬性就是物件不希望公開的屬性
私有方法就是方法不希望公開的方法
定義方法:
在定義屬性或方法時,在屬性或方法前面加兩個下劃線,定義的就是
私有屬性和私有方法
1、訪問私有屬性和私有方法
# 這樣年齡是私密的無法被訪問,訪問會出錯
class Women():
def __init__(self,name):
self.name = name
self.__age = 18 # 私有屬性不可以被訪問
def __secret(self): # 私有方法不可以被訪問
print '%s的年齡是%d'%(self.name,self.__age)
lily = Women('lily')
# 私有屬性,在外界不允許被訪問
#print lily.age
# 私有方法,外界不允許直接訪問
lily.secret()
# 最後程式報錯無法訪問
2、父類的私有屬性和私有方法
desc:
父類的私有屬性和私有方法
1.子類物件不能在自己的方法內部,直接訪問父類的私有屬性和私有方法
2.子類物件可以通過父類的公有方法間接訪問到私有屬性和私有方法
私有屬性:私有屬性是物件的隱私,不對外公開,外界以及子類都不能直接訪問
私有方法:私有方法常用做一些內部的事情
"""
# 可以直接列印B的地址
class A(object):
pass
class B(object):
pass
b=B()
print b
3、外界不能直接訪問物件的私有屬性/呼叫的私有方法
class A(object):
def __init__(self):
# 在初始化方法中定義了一個私有屬性一個公有屬性
self.num1 = 100
self.__num2 = 200
# 定義私有方法
def __test(self):
print '私有方法%d%d'%(self.num1,self.__num2)
class B(A):
pass
# 建立一個子類物件
b=B()
print b
# 在外界不能直接訪問物件的私有屬性/呼叫的私有方法
print b.__num2
b.__test
5、子類方法中,不能直接訪問父類的私有屬性或者呼叫私有方法
class A(object):
def __init__(self):
# 在初始化方法中定義了一個私有屬性一個公有屬性
self.num1 = 100
self.__num2 = 200
# 定義私有方法
def __test(self):
print '私有方法%d%d'%(self.num1,self.__num2)
class B(A):
def demo(self):
# 在子類方法中,不能直接訪問父類的私有屬性
print '訪問父類的私有屬性%d'%self.__num2
self.__test()
pass
# 建立一個子類物件
b=B()
print b
b.demo()
6、子類可以訪問父類的私有屬性和方法
class A(object):
def __init__(self):
# 在初始化方法中定義了一個私有屬性一個公有屬性
self.num1 = 100
self.__num2 = 200
# 定義私有方法
def __test(self):
print '私有方法%d'%self.__num2
def test(self):
self.__test()
print '訪問父類的私有屬性%d' % self.__num2
class B(A):
def demo(self):
self.test()
pass
# 建立一個子類物件
b=B()
b.demo()
三、面向物件中的類
1、類的結構
例項:
1.使用面向物件開發,第一步是設計類
2.使用類名()建立物件,建立物件的動作有兩步
1.在記憶體中為物件分配空間
2.呼叫__init__初始化方法為物件初始化
3.物件建立後,記憶體中就有了一個物件的實實在在的存在--->例項
因此:
1.創建出來的物件叫做類的例項
2.建立物件的動作叫做例項化
3.物件的屬性叫做例項屬性
4.物件呼叫的方法叫做例項方法
在程式執行時:
1.物件各自呼叫自己的例項屬性
2.呼叫物件的方法,可以通過self
訪問自己的屬性
呼叫自己的方法
結論:
1.每一個物件有自己獨立的記憶體空間,儲存各自不同的屬性
2.多個物件的方法,在記憶體中只有一份,在呼叫方法時,需要把物件的傳遞到方法內部
2、類是一個特殊的屬性
python中一切皆物件
class AAA: 定義的類屬性屬於類物件
obj1 = AAA: 屬於例項物件
在執行程式時,類同樣會被載入到記憶體
在python中,類是一個特殊的物件-->類物件
除了封裝例項(物件)的屬性和方法外,類物件還可以有自己的屬性和方法
通過類名.的方式可以直接訪問類的屬性或者呼叫類的方法
3、類屬性和類方法
使用類名()建立物件時,python的直譯器會呼叫__new__方法來分配空間
__new__是一個由object其類提供的內建的靜態方法,主要有兩個作用:
在記憶體中為物件分配空間
返回物件的引用
python的直譯器獲得物件的引用後,將引用作為第一個引數,傳遞給__init__
方法.
#__new__:負責給物件分配空間__init__負責給物件初始化
單例:讓類建立的物件
在系統中只有唯一的一個實現
只執行一次初始化操作
在每次使用類名()建立物件時,python的直譯器自會呼叫兩個方法:
__new__ 給記憶體分配空間
__init__ 物件初始化
4、計數器功能
class Tool(object):
# 1.使用了賦值語句定義類屬性,記錄所有工具的數量
count = 0
def __init__(self,name):
self.name = name
# 讓類屬性的值+1
Tool.count += 1
# 建立工具物件,會自動呼叫初始化方法
tool1 = Tool('鋤頭')
tool2 = Tool('梯子')
tool3 = Tool('榔頭')
# 輸出工具物件的總數
# 使用類名.屬性名來獲取
print Tool.count
5、類方法
類屬性就是針對類物件定義的屬性
使用賦值語句在class關鍵字下方定義類屬性
類屬性用於記錄於這個類相關的特性
類方法就是針對類物件定義的方法
在類方法內部就可以直接訪問類屬性或者呼叫其他類方法
語法如下:
@classmethod
def 類方法(cls):
pass
6、類的案例
class Toy(object):
# 1.定義類屬性
count = 0
@classmethod
def show_toy_count(cls):
# cls.count:在類方法的內部,訪問當前的類屬性
print '玩具的數量為%d'%cls.count
def __init__(self,name):
self.name = name
# 讓類的屬性值+1
Toy.count += 1
# 建立玩具物件
toy1 = Toy('樂高')
toy2 = Toy('手槍')
toy3 = Toy('玩具車')
# 呼叫類方法
Toy.show_toy_count()
# 在方法的內部,可以直接訪問類屬性
7、靜態方法
在開發時,如果需要在類中封裝一個方法,這個方法:
即不需要訪問例項屬性或者呼叫例項方法
也不需要訪問類屬性或者呼叫類方法
這個時候可以把這個方法封裝成一個靜態方法
語法如下:
@staticmethod
def 靜態方法():
pass
靜態方法需要裝飾器@staticmethod來標識,告訴直譯器這是一個靜態方法
通過類名.靜態方法來進行呼叫
8、靜態方法的案例
class Cat(object):
@staticmethod
# 靜態方法不需要傳遞第一個引數:self
def call():
print '小貓喵喵叫~~~'
Cat.call()
四、綜合案例
1、示例一、
desc:
需求:
1.設計一個Game類
2.屬性
類屬性:記錄遊戲的歷史最高分
(與這個遊戲有關係,與每次遊戲無關)
例項屬性:記錄當前的遊戲玩家
3.方法:
靜態方法:方法show_help顯示遊戲幫助資訊
類方法:方法show_top_score顯示歷史最高分
例項方法:方法start_game開始當前玩家的遊戲
4.主程式步驟:
1.檢視幫助資訊
2.檢視歷史最高分
3.建立遊戲物件,開始遊戲
"""
class Game(object):
# 記錄歷史最高分
top_score = 0
def __init__(self,player_name):
self.player_name = player_name
@staticmethod
def show_help():
print '遊戲幫助'
@classmethod
def show_top_score(cls):
print '歷史記錄%d'%cls.top_score
def start_game(self):
print '%s開始遊戲了'%self.player_name
# 1.檢視遊戲幫助
Game.show_help()
# 2.檢視歷史最高分
Game.show_top_score()
# 3.建立遊戲物件
game = Game('蛋蛋')
game.start_game()
案例小結:
1.例項方法:方法內部需要訪問例項屬性
2.類方法:方法內部只需要訪問類屬性
3.靜態方法:方法內部不需要訪問例項屬性和類屬性
提問:如果方法內部,既要訪問例項屬性,又要訪問類屬性,應該定義例項方法
2、**kwargs
引數表示的就是一個字典
五、單例設計模式
1、示例一、
需求:單例設計模式
例如:在音樂播放器播放時只能播放一首歌
用多個播放器也一樣,使其只播放一首歌
結果會播放兩首歌,需要改正
"""
class MusicPlayer(object):
def __new__(cls, *args, **kwargs):
# 第一個引數 cls:哪一個類呼叫,就傳遞哪個類
# 第二個引數 *args:多值引數
# 第三個引數 **kwargs:多值的字典的引數
# 建立物件的時候,new方法會被自動呼叫
print '建立物件,分配空間'
# 為物件分配空間
instance = object.__new__(cls)
# 返回物件的引用
return instance
def __init__(self):
print '播放器初始化'
player1 = MusicPlayer()
print player1
player2 = MusicPlayer()
print player2
2、進階版示例二:功能就是保證一個播放器只會播放一首歌
class MusicPlayer(object):
instance = None
def __new__(cls, *args, **kwargs):
# 第一個引數 cls:哪一個類呼叫,就傳遞哪個類
# 第二個引數 *args:多值引數
# 第三個引數 **kwargs:多值的字典的引數
# 建立物件的時候,new方法會被自動呼叫
if cls.instance is None:
cls.instance = object.__new__(cls)
return cls.instance
player1 = MusicPlayer()
print player1
player2 = MusicPlayer()
print player2
3、最終版示例三(提示字元也輸出一遍)
class MusicPlayer(object):
instance = None
init_flag = False
def __new__(cls, *args, **kwargs):
# 第一個引數 cls:哪一個類呼叫,就傳遞哪個類
# 第二個引數 *args:多值引數
# 第三個引數 **kwargs:多值的字典的引數
# 建立物件的時候,new方法會被自動呼叫
if cls.instance is None:
cls.instance = object.__new__(cls)
return cls.instance
def __init__(self):
if MusicPlayer.init_flag:
return
print '初始化播放器'
MusicPlayer.init_flag = True
player1 = MusicPlayer()
print player1
player2 = MusicPlayer()
print player2
六、Python新式類與經典類(舊式類)的區別:
Python中類分兩種:舊式類和新式類:
➤新式類都從object繼承,經典類不需要。
新式類是自動呼叫object類的
python3.幾版本後可以自動呼叫基類(object類)
類的抽象化:類定義之後不呼叫是沒辦法輸出的。
在Python 3.x中取消了經典類,預設都是新式類,並且不必顯式的繼承object,也就是說:
class Person(object):pass
class Person():pass
class Person:pass
三種寫法並無區別,推薦第一種
但是在Python2.x中,預設都是經典類,只有顯式繼承了object才是新式類,即:
class Person(object):pass 新式類寫法
class Person():pass 經典類寫法
class Person:pass 經典類寫法
1、新式類的寫法
In [1]: class A(object): 繼承object類,新式類
...: pass
...:
In [2]: a = A() 建立物件
In [3]: dir(a) 內建方法特別多,dir查詢物件的屬性
Out[3]:
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__']
2、經典類的寫法
In [4]: class A(): 繼承舊式類也叫做經典類
pass
...:
In [5]: a = A() 建立物件
In [6]: dir(a) 內建方法很少
Out[6]: ['__doc__', '__module__']