淺談 python的類和對象

淺談 python的類

 剛結束了python的方法,開始看類的時候有點迷糊,類的屬性和方法,對象的屬性和方法,構造函數,傳參。下面就一點點來 分析下。
 
類(Class) 官方給出的解釋是 用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例。
    這裏表示 類裏可以有多個屬性,也可以有多個方法。同時也有自己的字段。
    這裏的屬性 官方語言叫做 類變量,屬於這個類的公用部分,誰都可以來用,所以通常不作爲實例變量使用,就是一個符號。而方法,則是在類中
    定義的函數,可以理解爲類的行爲部分。
    

下面展示了類的成員:      

                                           普通字段
                                字段:
                                            靜態字段
                                                普通方法
                類成員:方法:    類方法
                                                靜態方法
                                屬性: 普通屬性
                        
                        
        字段: 普通字段屬於對象,靜態字段屬於類,如
            class Province:
                # 靜態字段
                country = '中國'
                def __init__(self, name):
                    # 普通字段        普通字段在每個對象中都要保存一份
                    self.name = name
            # 直接訪問普通字段
            obj = Province('河北省')
            print obj.name
            # 直接訪問靜態字段        靜態字段在內存中只保存一份
            Province.country
                
        方法:    
                class Foo:
                    def __init__(self, name):
                        self.name = name
                    def __init__(self):
                        pass
                    def ord_func(self):
                        """ 定義普通方法,至少有一個self參數 """
                        # print self.name
                        print('普通方法')
                    @classmethod  #表示下面的方法是類方法  將類本身作爲對象進行操作的方法
                    def class_func(cls):
                        """ 定義類方法,至少有一個cls參數 """
                        print('類方法')
                    @staticmethod   #標明這是一個靜態方法
                    def static_func():
                        """ 定義靜態方法 ,無默認參數"""
                        print('靜態方法')
                # 調用普通方法
                f = Foo()
                f.ord_func()
                # 調用類方法
                Foo.class_func()
                # 調用靜態方法
                Foo.static_func()
        
        屬性:
                class Foo:
                    def func(self):
                        pass
                    # 定義屬性
                    @property
                    def prop(self):
                        pass
                # ############### 調用 ###############
                foo_obj = Foo()
                foo_obj.func()
                foo_obj.prop   #調用屬性
                
                注意:
                    定義時,在普通方法的基礎上添加 @property 裝飾器;
                    定義時,屬性僅有一個self參數
                    調用時,無需括號
                               方法:foo_obj.func()
                               屬性:foo_obj.prop

                注意:屬性存在意義是:訪問屬性時可以製造出和訪問字段完全相同的假象

                        屬性由方法變種而來,如果Python中沒有屬性,方法完全可以代替其功能。
                            
實例化:通過類創建出一個對象,叫做實例化一個類。這裏創建出的對象,官方語言是:通過類定義的數據結構實例。對象包括兩個數據成員(類變量和實例變量)和方法。、

這樣  纔有了類 和對象 兩個概念,類 一般不生成實例變量,當然你可以當做默認值來給他賦值。
比如 A = AA()  AA.name  在A中也可以使用,A.name = AA.name 的默認值,如果你賦予了 A.name 值以後,等同於 A.name  覆蓋了AA.name 的值,如果不想要A.name 的值,那麼直接 del A.name
然後再打印 A.name  你會發現 A.name  就是 AA.name 的默認值了,當然,一般情況下不建議把  AA.name 作爲實例變量使用,僅僅是類成員。
就是說 --------   如果增加了類屬性,實例屬性一定會增加,但是增加了實例屬性,類屬性不受影響

好吧,接下來就是 類中的成員變量的訪問入口,注意,類中創建了成員變量 比如上面的 AA.name  在 AA這個類的方法內是無法直接訪問的,這點和java不同,python 需要一個領路人(self)
通過 self.name 纔可以在類的方法內訪問這個屬性的值。

最需要注意的一點:
如果在類初始化中創建一個變量(或者類初始化的變量)  該變量在類中任何一個方法中被重新修改,那麼無論是其他方法調用還是被實例化的
對象調用,這個變量的值都會隨着改變而改變 下面我們看下他們的name是否改變,結果證實  name 也會隨着變化的。    
    ***之所以不推薦創建類的屬性值 是因爲這個是可變的,並且任何一處定義了都能改變值,維護非常困難,一般建議通過self 來傳值

如:
import datetime as time

class Alarm(object):
     alarm_name='不在位指示'
     alarm_id=0
     alarm_start=time.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

     def getAlarmByID(self):
         print('根據 告警ID 獲取告警:',self.alarm_id)
         return "123"

     def testAlarm(self):
         print('測試告警信息 alarm_name = ',self.alarm_name,'  alarm_id= ',self.alarm_id,'  alarm_start=',self.alarm_start)
     def test2(self):
         print("測試 str 參數 = ",str,'  alarm_name= ',self.alarm_name)
         self.alarm_name='AIS'
         return self.alarm_name
     def test3(self):
         print(self.alarm_name)

aa = Alarm()
aa.alarm_name = 'R_LOS'  #這裏開始修改 alarm_name 的值
aa.test2()            #這裏 R_LOS 會取代 不在位指示  同時在方法 test2 中再次修改 alarm_name 的值
print(aa.alarm_name)  這裏最終的值是test2 中修改的 AIS
aa.test3()                #不管是 test3裏的打印 還是 aa.alarm_name 的打印,都是 test2 最後修改的那個值 即  AIS
print(aa.alarm_name)  # AIS

上述結果說明,在類的方法內部試圖修改類屬性的值是愚蠢的做法,因爲這個是可變的,這樣會導致維護起來非常困難,一般建議通過 self 來傳值



類的繼承:  inheritance    
            Object  = Class(SuperClass)
                注意: 子類中在對  __init__ 內的變量在其他任何方法上做修改,內外值都會隨着改變
                
            子類重寫了父類的屬性或者方法後,父類的信息都會改變
            
            多重繼承:  class A  classB  c = classC(A,B) 順序按照AB 順序來
                Super() 調用顯示父類的屬性或函數  在重寫的時候調用可以延續父類的屬性或方法,子類可選是否借用父類
                        格式爲: super(父類,參數self).__init__() 父類函數
            靜態方法: 使用前提,需要一個參數不能讓別人進行修改,在非特定環境下該靜態變量或方法外部修改無效,只有在特定環境下修改纔可行
                    如  IND = 'ON'        
                        class Kls(object):
                            def __init__(self, data):
                                self.data = data
                            @staticmethod  表明這是一個靜態方法
                            def checkind():    
                                IND = "OFF"        ### 只有在這裏修改纔有效
                                return (IND == 'ON')   在別的地方也可以修改這個值 但是在調用這個方法的時候 IND 始終是OFF (已修改)  不會再有別的值
                            def do_reset(self):
                                IND = 'OFF'  ##這裏修改無效
                                if self.checkind():
                                    print('Reset done for:', self.data)
                            def set_db(self):
                                if self.checkind():
                                    self.db = 'New db connection'
                                print('DB connection made for: ', self.data)
                                
            類方法: @classmethod 表示下面的方法是類方法  將類本身作爲對象進行操作的方法
                     注意 必須至少有一個參數 cls 來代替 self  其餘自定義
        
            多態: 著名的鴨子測試: 當我們看到一隻鳥走起來像鴨子,游泳起來像鴨子,叫起來也像鴨子,那麼這隻鳥就可以被稱爲鴨子
                 意思是:一個對象有效的語義,不是由繼承自特定的類或實現特定的接口,而是由當前的方法屬和屬性的集合決定的。
                 注意: 類型檢查是毀掉多態的利器   type() isinstance()  issubclass()  慎用!
            
        
        類的封裝和私有化: 方法 或者屬性 前面添加上 __ 即可 這樣的話外部無法訪問,但可以通過方法來訪問
                如果想在外部訪問私有屬性或方法前添加上 @property 可以直接訪問 對象.屬性
                    class Person:
                        __age = int()
                        def __init__(self,name):
                            self.name = name
                            self.__age = 10

                        @property    #################這裏可以直接訪問到了
                        def age(self):
                            print(self.name,' 的年齡是:',self.__age)



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章