Python學(xué)習(xí)筆記二十四( 元類 )

__class__屬性

__class__屬性可以查看對象的類型.

class Person(object):
    pass


person = Person()

print(person.__class__)

# 運(yùn)行結(jié)果
# <class '__main__.Person'>

Person 類的實(shí)例對象person 的類型時Person 類類型, Python 是面向?qū)ο蟮恼Z言, 那么Person 的類對象的類型又是什么?

class Person(object):
    pass


person = Person()

print(person.__class__)
print(Person.__class__)

# int 的類型
print(int.__class__)
# str 的類型
print(str.__class__)

# 運(yùn)行結(jié)果
# <class '__main__.Person'>
# <class 'type'>
# <class 'type'>
# <class 'type'>

Person / int / str 的類對象的類型都是type 類類型.
那么type類對象 的類型又是什么類型?

class Person(object):
    pass


print(Person.__class__.__class__)

# int 的類型
print(int.__class__.__class__)
# str 的類型
print(str.__class__.__class__)
print(type.__class__)

# 運(yùn)行結(jié)果
# <class 'type'>
# <class 'type'>
# <class 'type'>
# <class 'type'>

type 類對象的類型還是type 類類型, 那么type 類是干嘛的?

元類

type 類是元類, Python中所有的類默認(rèn)都是使用type 類創(chuàng)建的, type 類屬于Python中的高深魔法, 一般很少用到.

   """
    type(object_or_name, bases, dict)
    type(object) -> the object's type
    type(name, bases, dict) -> a new type
    """

type類有兩個功能,

  • type(object) : 一個參數(shù),返回object 的類型
  • type(name, bases, dict) : 三個參數(shù),返回一個新的類型
type(object)
class Person(object):
    pass


person = Person()

print(type(person))  # 查看person 實(shí)例對象的類型
print(type(Person))  # 查看Person 類對象的類型

# 運(yùn)行結(jié)果
# <class '__main__.Person'>
# <class 'type'>
type(name, bases, dict)

使用type 創(chuàng)建一個類

正常創(chuàng)建Person 類的子類Teacher

class Person(object):
    pass


class Teacher(Person):
    def __init__(self):
        self.name = "Teacher"


# help() 函數(shù)用于查看函數(shù)或模塊用途的詳細(xì)說明。
print(help(Teacher))

元類創(chuàng)建Person 類的子類Student

class Person(object):
    pass


def __init__(self):
    self.name = "Student"

# "Student" 是類名
Student = type("Student", (Person,), {"__init__": __init__})
# help() 函數(shù)用于查看函數(shù)或模塊用途的詳細(xì)說明腐泻。
print(help(Student))

運(yùn)行結(jié)果對比


01對比.png
元類創(chuàng)建類
class Person(object):
    pass


def __init__(self):
    pass


@classmethod
def test_cls_func(cls):
    pass


@staticmethod
def test_static_func():
    pass


Student = type(
    "Student",  # 類名
    (Person,),  # 所有的父類,使用元組傳參

    {"__init__": __init__,  # 實(shí)例方法
     "test_cls_func": test_cls_func,  # 類方法
     "test_static_func": test_static_func,  # 靜態(tài)方法
     "type_name": "student",  # 類屬性
     }  # 類包含的屬性
)

print(help(Student))

# 運(yùn)行結(jié)果
# {'__init__': <function __init__ at 0x0000016D93862E18>,
# 'test_cls_func': <classmethod object at 0x0000016D95716400>,
# 'test_static_func': <staticmethod object at 0x0000016D95716BA8>,
# 'type_name': 'student',
# '__module__': '__main__',
# '__doc__': None}

運(yùn)行結(jié)果


02運(yùn)行結(jié)果.png

注意:

class Person(object):
    pass

# Student 只是一個變量,引用了type 返回的Student類型
Student = type("Student", (Person,), {"type_name": "student", })
student = Student()

# Student2 只是一個變量,引用了type 返回的Student類型
Student2 = type("Student", (Person,), {"type_name": "student", })
student2 = Student2()

print(type(student))
print(type(student2))

# 運(yùn)行結(jié)果
# <class '__main__.Student'>
# <class '__main__.Student'>

元類改造類

元類除了能創(chuàng)建一個類,也能改造一個類.

class ChangeClass(type):  # 這個必須是type子類
    def __new__(cls, class_name, super_names, attrs):
        print("class_name: %s" % class_name)
        print("super_names: %s" % super_names)
        print("attrs: %s" % attrs)

        tmp_attrs = dict()

        # 將所有 實(shí)例/類/靜態(tài) 方法的名字改為小寫
        for key, value in attrs.items():

            # hasattr(value, "__call__")  判斷值是一個func 對象,
            # 不能使用isinstance , 因?yàn)?class function: # TODO not defined in builtins!(源碼)
            if hasattr(value, "__call__") or isinstance(value, classmethod) or isinstance(value, staticmethod):
                tmp_attrs[key.lower()] = value
                continue
            tmp_attrs[key] = value

        return type.__new__(cls, class_name, super_names, tmp_attrs)  # 一般工作中用這種方式


class Preson(object, metaclass=ChangeClass):
    cls_name = "cls_name"

    def __init__(self):
        self.self_name = "self_name"

    @classmethod
    def Test_Cls_Func(cls):
        pass


print("改造后 " + "*" * 20)
print(Preson.__dict__)
# 運(yùn)行結(jié)果
# class_name: Preson
# super_names: <class 'object'>
# attrs: {'__module__': '__main__', '__qualname__': 'Preson', 'cls_name': 'cls_name', 
#       '__init__': <function Preson.__init__ at 0x000002260B828A60>, 
#       'Test_Cls_Func': <classmethod object at 0x000002260B826F28>}
# 改造后 ********************
# {'__module__': '__main__', 'cls_name': 'cls_name', 
#       '__init__': <function Preson.__init__ at 0x000002260B828A60>, 
#       'test_cls_func': <classmethod object at 0x000002260B826F28>, 
#       '__dict__': <attribute '__dict__' of 'Preson' objects>, 
#       '__weakref__': <attribute '__weakref__' of 'Preson' objects>, '__doc__': None}


結(jié)語

經(jīng)過近兩個月的努力, 寫下了Python 學(xué)習(xí)筆記系列共計二十四篇, 限于本人精力以及能力, 篇章中如有錯誤之處, 煩請各位告知, 便于更正, 以利他人.

是結(jié)束亦是開始, 革命尚未成功, 同志仍需努力.

Html / Css / JavaScript 學(xué)習(xí) : w3school 在線教程
Python 教程 : 廖雪峰 Python 教程
菜鳥教程


到此結(jié)??DragonFangQy 2018.5.27

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末澜薄,一起剝皮案震驚了整個濱河市秸侣,隨后出現(xiàn)的幾起案子掌逛,更是在濱河造成了極大的恐慌陨仅,老刑警劉巖舔痪,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寓调,死亡現(xiàn)場離奇詭異,居然都是意外死亡锄码,警方通過查閱死者的電腦和手機(jī)夺英,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門晌涕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人痛悯,你說我怎么就攤上這事余黎。” “怎么了载萌?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵惧财,是天一觀的道長。 經(jīng)常有香客問我扭仁,道長垮衷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任乖坠,我火速辦了婚禮搀突,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘熊泵。我一直安慰自己仰迁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布顽分。 她就那樣靜靜地躺著徐许,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卒蘸。 梳的紋絲不亂的頭發(fā)上绊寻,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音悬秉,去河邊找鬼澄步。 笑死,一個胖子當(dāng)著我的面吹牛和泌,可吹牛的內(nèi)容都是我干的村缸。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼武氓,長吁一口氣:“原來是場噩夢啊……” “哼梯皿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起县恕,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤东羹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后忠烛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體属提,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了冤议。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斟薇。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖恕酸,靈堂內(nèi)的尸體忽然破棺而出堪滨,到底是詐尸還是另有隱情,我是刑警寧澤蕊温,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布袱箱,位于F島的核電站,受9級特大地震影響义矛,放射性物質(zhì)發(fā)生泄漏犯眠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一症革、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸯旁,春花似錦噪矛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至韭赘,卻和暖如春缩滨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泉瞻。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工脉漏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人袖牙。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓侧巨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鞭达。 傳聞我的和親對象是個殘疾皇子司忱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容