1. 程式人生 > >python _ 面向物件中類及其屬性方法

python _ 面向物件中類及其屬性方法

一、面向物件中的內建方法

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__']

這裡寫圖片描述