1. 程式人生 > 實用技巧 >Python學習筆記Day06~07 - 類

Python學習筆記Day06~07 - 類

目錄

# 普通類的建立方法
# class Foo(object):
#     def __init__(self, name):
#         self.name = name
#
#
# f = Foo("alex")
# print(type(f))
# print(type(Foo))

# 類的特殊建立方法
def func(self):
    print('hello %s' %self.name)
def __init__(self,name,age):
    self.name = name
    self.age = age

Foo = type('Foo', (object,), {'func': func,
                       '__init__':__init__})    # 所有類都是type的例項化
f = Foo("Chrn",22)
f.func()
print(type(Foo))

1.建構函式:在例項化時做一些類的初始化工作

2.解構函式:在例項釋放、銷燬的時候自動執行的,通常用於做一些收尾工作,

        如關閉一些資料庫連線,關閉開啟的臨時檔案

3.例項變數與類變數,類變數是大家共用的屬性,能節省記憶體開銷

4.靜態屬性與動態屬性,分別表示變數和方法

5.私有方法,私有屬性,加__,在外部無法呼叫

6.封裝

7.繼承 作用就是減少程式碼量,子類可以重構父類的方法,可以繼承多個父類

    py2 經典類是按深度優先來繼承的,新式類是按廣度優先來繼承的
    py3 經典類和新式類都是統一按廣度優先來繼承的

8.多型 一種介面,多種形態

class Animal:
    def __init__(self, name):  # Constructor of the class
        self.name = name

    def talk(self):  # Abstract method, defined by convention only
        pass #raise NotImplementedError("Subclass must implement abstract method")

    @staticmethod
    def animal_talk(obj):
        obj.talk()

class Cat(Animal):
    def talk(self):
        print('Meow!')


class Dog(Animal):
    def talk(self):
        print('Woof! Woof!')


d = Dog("陳榮華")
#d.talk()

c = Cat("徐良偉")
#c.talk()

# def animal_talk(obj):
#     obj.talk()

Animal.animal_talk(c)   # 通過一個介面,按不同的子類實現不同的效果
Animal.animal_talk(d)

類方法、靜態方法和屬性方法

9.靜態方法@staticmethod:不能訪問類變數和例項變數,就相當於一個普通函式,與類的其他屬性無關

# http://www.cnblogs.com/alex3714/articles/5213184.html

class Dog(object):
    # __metaclass__ = MyType    #指定該類由誰例項化
    # def __new__(cls, *args, **kwargs):
    # 類的生成、呼叫、順序依次是:__new__ --> __init__ --> __call__
    n = 123   # 類變數,可被例項變數覆蓋

    def __init__(self, name):
        self.name = name    # 例項變數(靜態屬性),作用域是例項本身

    # @classmethod  # 類方法:只能訪問類變數,不能訪問例項變數
    # @staticmethod # 靜態方法:不能訪問類變數和例項變數,就相當於一個普通函式,與類的其他屬性無關
    # @property   # 屬性方法:呼叫不需要加括號,也不能傳引數
    def eat(self):  #類的方法(動態屬性)
        print('%s is eatting...' % self.name)


    def __call__(self, *args, **kwargs):
        print('例項物件後面加括號觸發')    # 用d()呼叫

    def __str__(self):
        return "列印例項物件時輸出返回的值"    # 用d 呼叫

    def __getitem__(self, item):
        print('索引獲取,如字典')
        # 例項:key_value
        # result = obj['k1']  # 自動觸發執行 __getitem__
        # obj['k2'] = 'alex'  # 自動觸發執行 __setitem__
        # del obj['k1'] # 自動觸發執行 __setitem__

    def __setitem__(self, key, value):
        print('索引設定')

    def __delitem__(self, key):
        print('索引刪除')


d = Dog('金毛')   #例項化

d.bullet_prove = True   #新增例項變數
del d.name     #刪除例項的變數
d.n = '改變類變數'    #相當於新增一個例項變數,原本的類變數並沒有改變

#類的特殊成員方法
d.__doc__   #輸出類的描述資訊
d.__module__    #輸出類所屬模組lib
d.__class__ #輸出類所屬類
d.__dict__  #檢視例項中的所有變數
Dog.__dict__  #檢視類中的所有成員

10.類方法@classmethod:只能訪問類變數,不能訪問例項變數

11.屬性方法@property:把一個方法變成一個靜態屬性,呼叫不需要加括號,也不能傳引數

要給屬性方法傳引數只能使用.setter再寫一個同名方法
介面,對使用者來講,只需要屬性的結果,不需要知道其中的過程

class Flight(object):
    def __init__(self,name):
        self.flight_name = name


    def checking_status(self):
        print("checking flight %s status " % self.flight_name)
        return  0

    @property
    def flight_status(self):
        status = self.checking_status()
        if status == 0 :
            print("flight got canceled...")
        elif status == 1 :
            print("flight is arrived...")
        elif status == 2:
            print("flight has departured already...")
        else:
            print("cannot confirm the flight status...,please check later")
    @flight_status.setter
    def flight_status(self,status):
        print("flight %s has changed status to %s" %(self.flight_name,status))
f = Flight("CA980")
f.flight_status
f.flight_status = 2

12.類的特殊成員用法:doc,module,class,dict,call,str,getitem,setitem,delitem

# hasattr(obj,name_str) , 判斷一個物件obj裡是否有對應的name_str字串的方法
# getattr(obj,name_str), 根據字串去獲取obj物件裡的對應的方法的記憶體地址
# setattr(obj,'y',z), is equivalent to ``obj.y = z''
# delattr(obj,z)

def bulk(self):
    print("%s is yelling...." % self.name)


class Dog(object):
    def __init__(self, name):
        self.name = name

    def eat(self, food):
        print("%s is eating..." % self.name, food)


d = Dog("NiuHanYang")
choice = input(">>:").strip()

if hasattr(d, choice):  # 判斷例項是否有這個方法
    getattr(d, choice)  # 獲得例項中的方法
else:
    setattr(d, choice, bulk)  # d.talk = bulk   為例項新增方法
    func = getattr(d, choice)
    func(d)

13.所有類的資料型別就是type,通過__metaclass__可自定義

類的建立過程

class MyType(type):
    def __init__(self, what, bases=None, dict=None):    # 建立類時執行的第一階段
        print("--MyType init---")
        super(MyType, self).__init__(what, bases, dict)

    def __call__(self, *args, **kwargs):        # 建立例項時執行的第二階段第一步
        print("--MyType call---")
        obj = self.__new__(self, *args, **kwargs)
        obj.data = {"name":111}
        self.__init__(obj, *args, **kwargs)


class Foo(object):
    __metaclass__ = MyType  # 定製類的建立過程,預設type

    def __init__(self, name):       # 建立例項時執行的第二階段第三步
        self.name = name
        print("Foo ---init__")

    def __new__(cls, *args, **kwargs):  # 類自帶,用來建立例項,先於__init__執行,第二階段第二步
        print("Foo --new--")
        #print(object.__new__(cls))
        return object.__new__(cls) # 繼承父類的__new__方法     #cls相當於類的self


# 第一階段:直譯器從上到下執行程式碼建立Foo類,執行MyType的__init__方法
# 第二階段:通過Foo類建立obj物件 __call__,__new__,__init__
obj = Foo("Alex")
print(obj.name)