Python類和對象

類與對象

類即類別、種類,是面向對象設計最重要的概念,對象是屬性與方法的結合體,而類則是一系列對象類似的屬性與方法的高度歸納.即類是把類似事物進行抽象,而對象的一個具體的實例.app

在Python裏面,任何都是類,str等類型也是一種類.ssh

在程序代碼裏面,咱們必須對事物進行建模,抽象出它的屬性(特徵,好比美醜等等)與方法(動做等動態行爲),而後才能創建一個類;有了一個類以後,咱們才能創建相關的對象,即實例函數

class Dog(object):      ##經過class方法能夠建立一個類
    def __init__(self, name, speice, master, age):  ##賦予該類屬性
        self.name = name
        self.speice = speice
        self.master = master
        self.age = age

    def dog_bark(self):   ##賦予方法
        print("%s正在汪汪汪....." %self.name)

    def eat_food(self):  ##必須寫self這種形參,關聯類
        print("%s正在吃飯"%self.name)


dog_1 = Dog("旺財", "哈士奇", "Jack", 7)  ##實例化一個對象出來
print(dog_1.name)
dog_1.dog_bark()  ##經過"."來調方法和屬性

旺財
旺財正在汪汪汪.....

print(dog_1.__dict__) ##能夠打印出對象的屬性字典,另外類裏面並無方法,它須要到類裏面調用
print(Dog.__dict__)   ##打印Dog類的屬性字典

{'name': '旺財', 'speice': '哈士奇', 'master': 'Jack', 'age': 7}
{'__module__': '__main__', '__init__': <function Dog.__init__ at 0x0000027E895CCF28>, 'dog_bark': <function Dog.dog_bark at 0x0000027E895D6048>, 'eat_food': <function Dog.eat_food at 0x0000027E895D60D0>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None}

dog_1.name = "二哈"
print(dog_1.__dict__)   ##能夠這樣修改屬性值,而若是在類裏面找不到就會向上找,但不會出類的範圍;
                        ##"__dict__"方法是調出對象的屬性字典
{'name': '二哈', 'speice': '哈士奇', 'master': 'Jack', 'age': 7}

其餘方法

#python爲類內置的特殊屬性
類名.__name__# 類的名字(字符串)
類名.__doc__# 類的文檔字符串
類名.__base__# 類的第一個父類(在講繼承時會講)
類名.__bases__# 類全部父類構成的元組(在講繼承時會講)
類名.__dict__# 類的字典屬性
類名.__module__# 類定義所在的模塊
類名.__class__# 實例對應的類(僅新式類中)

###__init__方法
# 一、該方法內能夠有任意的python代碼
# 二、必定不能有返回值
##當咱們創建對象時,就會觸發__init__方法

繼承

繼承是一種建立新類的方式,新類能夠繼承一種基類(父類),在Python裏面能夠繼承多個類;新建的類又叫作派生類或子類.在Python裏面class創建的類,也繼承於一個叫作「object」的基類.咱們可使用繼承來減小重用性,使得代碼量減小.工具

class Create(object):     ##建立一個基類
    def __init__(self, name, speice, age):
        self.name = name
        self.speice = speice
        self.age = age

    def eat_food(self):
        print("%s is eating!"%self.name)

    def sleep(self):
        print("%s is sleeping!"%self.name)

class Dog(Create):  ##經過這個方式,繼承基類

dog = Dog("二哈", "哈士奇", 5)
dog.sleep()

二哈 is sleeping!
>>> SubClass1.__bases__ #__base__只查看從左到右繼承的第一個子類,__bases__則是查看全部繼承的父類
(<class '__main__.ParentClass1'>,)
>>> SubClass2.__bases__
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

經典類和新式類

在python2中,沒有顯式的繼承object類的類,以及該類的子類,都是經典類;顯式地聲明繼承object的類,以及該類的子類,都是新式類
在python3中,不管是否繼承object,都默認繼承object,即python3中全部類均爲新式類this

派生

然子類也能夠添加本身新的屬性或者在本身這裏從新定義這些屬性(不會影響到父類),須要注意的是,一旦從新定義了本身的屬性且與父類重名,那麼調用新增的屬性時,就以本身爲準了設計

class Create(object):
    def __init__(self, name, speice, age):
        self.name = name
        self.speice = speice
        self.age = age

    def eat_food(self):
        print("%s is eating!"%self.name)

    def sleep(self):
        print("%s is sleeping!"%self.name)

class Dog(Create):
    def __init__(self, name, master, age):  ##覆蓋了原來的
        self.name = name 
        self.master = master
        self.age = age

    def eat_food(self):
        print("%s的狗狗正在吃飯" %self.master)

dog = Dog("金毛", "Hermaeus", 15)
dog.eat_food()
print(dog.master)

組合

在一個類中以另一個類的對象做爲數據屬性,稱爲類的組合代理

class Hand(object):
    pass

class Head(object):
    pass

class Body(object):
    pass

class People(object):
    def __init__(self):
        self.hand = Hand()  ##即把其餘類導入進來
        self.head = Head()
        self.body = Body()

接口、歸一化設計與抽象類

接口指的是本身提供給使用者來調用本身功能的方式\方法\入口code

接口提取了一羣類共同的函數,能夠把接口當作一個函數的集合;而後讓子類去實現接口中的函數。orm

這麼作的意義在於歸一化,什麼叫歸一化,就是隻要是基於同一個接口實現的類,那麼全部的這些類產生的對象在使用時,從用法上來講都同樣。

歸一化的好處在於:

  1. 歸一化讓使用者無需關心對象的類是什麼,只須要的知道這些對象都具有某些功能就能夠了,這極大地下降了使用者的使用難度。
  2. 歸一化使得高層的外部使用者能夠不加區分的處理全部接口兼容的對象集合

抽象類是一個特殊的類,它的特殊之處在於只能被繼承,不能被實例化

import abc   ##調用該方法實現抽象類
class All_file(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def read(self):
        pass

    @abc.abstractmethod
    def write(self):
        pass

class Disk(All_file):
    def read(self):
        print('disk read')

    def write(self):
        print('disk write')

class Cdrom(All_file):
    def read(self):
        print('cdrom read')

    def write(self):
        print('cdrom write')

class Mem(All_file):
    def read(self):
        print('mem read')

    def write(self):
        print('mem write')

m1=Mem()
m1.read()
m1.write()

mem read
mem write

繼承實現的原理

當類是經典類時會遵循深度優先;是新類是會遵循廣度優先

對於你定義的每個類,python會計算出一個方法解析順序(MRO)列表,這個MRO列表就是一個簡單的全部基類的線性順序列表

class A(object):
    def test(self):
        print('from A')

class B(A):
    def test(self):
        print('from B')

class C(A):
    def test(self):
        print('from C')

class D(B):
    def test(self):
        print('from D')

class E(C):
    def test(self):
        print('from E')

class F(D,E):
    pass


print(F.__mro__)

那麼就會產生一個和下列同樣的MRO列表,查找的順序是按着從左到右實現的,而子類會先於父類被檢查;若是有多個父類會根據它們在列表中的順序被檢查;當存在兩個合法的選擇,選擇第一個父類

(<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

子類中調用父類的方法

指名道姓

class Create(object):
    def __init__(self, name, speice, age):
        self.name = name
        self.speice = speice
        self.age = age

    def eat_food(self):
        print("%s is eating!"%self.name)

    def sleep(self):
        print("%s is sleeping!"%self.name)

class Dog(Create):
    def __init__(self, name, speice, age, master):
        Create.__init__(self, name, speice, age)    ##直接經過名字引用,須要self參數
        self.master = master

    def eat_food(self):
        print("%s的狗狗正在吃飯" %self.master)


dog = Dog("二哈", "哈士奇", 18, "Hermaeus")
dog.sleep()

super()方法

class Create(object):
    def __init__(self, name, speice, age):
        self.name = name
        self.speice = speice
        self.age = age

    def eat_food(self):
        print("%s is eating!"%self.name)

    def sleep(self):
        print("%s is sleeping!"%self.name)

class Dog(Create):
    def __init__(self, name, speice, age, master):
        super().__init__(name, speice, age)    ##經過super()來調用,可是絕對不能有self
        self.master = master

    def eat_food(self):
        print("%s的狗狗正在吃飯" %self.master)


dog = Dog("二哈", "哈士奇", 18, "Hermaeus")
dog.sleep()

多態與多態性

在面向對象方法中通常是這樣表述多態性:向不一樣的對象發送同一條消息,不一樣的對象在接收時會產生不一樣的行爲(即方法)。也就是說,每一個對象能夠用本身的方式去響應共同的消息。所謂消息,就是調用函數,不一樣的行爲就是指不一樣的實現,即執行不一樣的函數;分爲靜態多態動態多態.

>>> class Cat(Animal): #屬於動物的另一種形態:貓
...     def talk(self):
...         print('say miao')
... 
>>> def func(animal): #對於使用者來講,本身的代碼根本無需改動
...     animal.talk()
... 
>>> cat1=Cat() #實例出一隻貓
>>> func(cat1) #甚至連調用方式也無需改變,就能調用貓的talk功能
say miao

封裝

單下劃線開頭

#其實這僅僅這是一種變形操做且僅僅只在類定義階段發生變形
#類中全部單下劃線開頭的名稱如_x在約定上被認爲是封裝,讓人們在使用的過程當中不要調用,可是實際上沒有任何用

class A:
    _N=0 #約定不要使用
    def __init__(self):
        self._X=10 
    def _foo(self):
        print('from A')
    def bar(self):
        self._foo() 

#這種,在外部是能夠經過_x這個名字訪問到

雙下劃線開頭

#其實這僅僅這是一種變形操做且僅僅只在類定義階段發生變形
#類中全部雙下劃線開頭的名稱如__x都會在類定義時自動變造成:_類名__x的形式:

class A:
    __N=0 #類的數據屬性就應該是共享的,可是語法上是能夠把類的數據屬性設置成私有的如__N,會變形爲_A__N
    def __init__(self):
        self.__X=10 #變形爲self._A__X
    def __foo(self): #變形爲_A__foo
        print('from A')
    def bar(self):
        self.__foo() #只有在類內部才能夠經過__foo的形式訪問到.

#A._A__N是能夠訪問到的,
#這種,在外部是沒法經過__x這個名字訪問到

封裝的真諦在於明確地區份內外,封裝的屬性能夠直接在內部使用,而不能被外部直接使用,然而定義屬性的目的終歸是要用,外部要想用類隱藏的屬性,須要咱們爲其開闢接口,讓外部可以間接地用到咱們隱藏起來的屬性

封裝數據:將數據隱藏起來這不是目的.隱藏起來而後對外提供操做該數據的接口,而後咱們能夠在接口附加上對該數據操做的限制,以此完成對數據屬性操做的嚴格控制

封裝方法:目的是隔離複雜度,讓程序的一些細節不須要被使用者知道

在導入模塊的過程當中,from module import *時不能被導入,可是你from module import _private_module依然是能夠導入的

特性(property)

property是一種特殊的裝飾器,使用它時會執行一段功能(函數)而後返回值

class People:
    def __init__(self,name,weight,height):
        self.name=name
        self.weight=weight
        self.height=height
        
    @property
    def bmi(self):
        return self.weight / (self.height**2)

p1=People('Hermaeus',60,1.7)
print(p1.bmi)

將一個類的函數定義成特性之後,對象再去使用的時候obj.name,根本沒法察覺本身的name是執行了一個函數而後計算出來的,這種特性的使用方式遵循了統一訪問的原則

綁定方法(classmethod)

  1. 綁定到類的方法:用classmethod裝飾器裝飾的方法

    爲類量身定製,自動將類看成第一個參數傳入(其實對象也可調用,但仍將類看成第一個參數傳入)

  2. 綁定到對象的方法:沒有被任何裝飾器裝飾的方法

    爲對象量身定製,自動將對象看成第一個參數傳入(屬於類的函數,類能夠調用,可是必須按照函數的規則來,沒有自動傳值那麼一說)

class Room(object):
    tag=1
    def __init__(self,name,owner,width,length,heigh):
        self.name=name
        self.owner=owner
        self.width=width
        self.length=length
        self.heigh=heigh

    @classmethod
    def tell_info(cls,x):
        print(cls)
        print('-->',cls.tag,x)

Room.tell_info(10)

<class '__main__.Room'>
--> 1 10

非綁定方法(staticmethod)

不與類或對象綁定,類和對象均可以調用,可是沒有自動傳值那麼一說;就是一個普通工具而已

class Room(object):
    tag=1
    def __init__(self,name,owner,width,length,heigh):
        self.name=name
        self.owner=owner
        self.width=width
        self.length=length
        self.heigh=heigh

    @staticmethod    ##變成一個獨立的方法
    def get_area(x, y):
        res = x*y
        print("Area is %s" %res)
        
Room.get_area(2, 3)

Area is 6

isinstance(obj,cls)和issubclass(sub,super)

isinstance(obj,cls)判斷obj是不是類cls的對象

issubclass(sub,super)判斷sub類是不是super類的派生類

############
class Foo(object):
    pass

obj = Foo()

print(isinstance(obj, Foo))

############
class Func(object):
    pass

class Func1(Func):
    pass

print(issubclass(Func1, Func))

True
True

反射

經過字符串的形式操做對象相關的屬性.Python中的一切事物都是對象(均可以使用反射)

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

    def dog_bark(self):
        print("%s is barking!" %self.name)

    def eat_food(self):
        print("%s is eating!" %self.name)

dog = Dog("二哈", "Hermaeus", "哈士奇")

#####hasattr(object, attr)#########
##判斷在對象裏是否有某屬性
print(hasattr(dog, "name"))

True

#####getattr(object, name, default=None)#########
##獲得對象裏的某屬性,若是沒有返回default
print(getattr(dog, "name"))
print(getattr(dog, "afjaljf", "沒有"))

二哈
沒有

#####getattrsetattr(x, y, v)#########
##設置屬性
setattr(dog, "hobby", "拆家")
print(dog.__dict__)

{'name': '二哈', 'master': 'Hermaeus', 'species': '哈士奇', 'hobby': '拆家'}

#####delattr(x, y)#########
##刪除某屬性
delattr(dog, "name")
print(dog.__dict__)

{'master': 'Hermaeus', 'species': '哈士奇', 'hobby': '拆家'}

若是須要使用該方法的對象文件就是本身,那麼能夠調用sys模塊裏面的modules方法

import sys

def func1():
    print("From func1")

def func2():
    print("From func2")

this_module = sys.modules[__name__]

print(hasattr(this_module, "func1"))

True

動態導入模塊

import importlib

importlib.import_module("名字")

__setattr__,__delattr__,__getattr__

class Foo(object):
    x = 1
    def __init__(self, y):
        self.y = y

    def __getattr__(self, item):
        print("From __getattr__")

    def __setattr__(self, key, value):
        print("From __getattr__")

    def __delattr__(self, item):
        print("From __delattr")

##__setattr__添加/修改屬性會觸發它的執行
## 由於你重寫了__setattr__,凡是賦值操做都會觸發它的運行,那麼根本沒賦值,除非你直接操做屬性字典,不然永遠沒法賦值
##self.__dict__[key] = value  ===> 會把值直接添加到對象的屬性字典

##__delattr__刪除屬性的時候會觸發
##self.__dict__.pop(item)  ===> 直接刪除對象字典裏的值

##__getattr__只有在使用點調用屬性且屬性不存在的時候纔會觸發

二次加工標準類型經過

經過繼承派生的手段,基於標準數據類型來定製咱們本身的數據類型,新增或者改寫方法

class List(list):
    def append(self,p_object):
        if isinstance(p_object, int):
            raise TypeError("不支持int類型")  #raise方法能夠拋出錯誤
        super().append(p_object)

s1 = List(("a", 'b', 'c'))
print(s1)
s1.append(12)  ##報錯

…………………………………………………………………………………………
    raise TypeError("不支持int類型")
TypeError: 不支持int類型

受權是包裝的一個特性, 包裝一個類型一般是對已存在的類型的一些定製,這種作法能夠新建,修改或刪除原有產品的功能.其它的則保持原樣。受權的過程,便是全部更新的功能都是由新類的某部分來處理,但已存在的功能就受權給對象的默認屬性.而實現受權的關鍵點就是覆蓋__getattr__方法

import time
class HandleFile(object):
    def __init__(self, filename, mode, encoding = "UTF-8"):
        self.file = open(filename, mode)

    def write(self, context):
        t = time.strftime("%Y-%m-%d %T")
        self.file.write("%s %s" %(t, context))

    def __getattr__(self, item):   ##覆蓋了原來的方法,使得沒有的方法到open裏面找
        return getattr(self.file, item)  


f1 = HandleFile("b.txt", "w")
f1.write("Hello, World!")
f1.close()

__getattribute__

當__getattribute__與__getattr__同時存在,只會執行__getattrbute__,除非__getattribute__在執行過程當中拋出異常AttributeError

class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print('執行的是我')
        
    def __getattribute__(self, item):
        print('不論是否存在,我都會執行')
        raise AttributeError('哈哈') ##會執行一次__getattr__

f1=Foo(10)
f1.x
f1.xxxxxx

描述符(__get__,__set__,__delete__)

描述符本質就是一個新式類,在這個新式類中,至少實現了__get__(),__set__(),__delete__()中的一個,這也被稱爲描述符協議
__get__():調用一個屬性時,觸發
__set__():爲一個屬性賦值時,觸發
__delete__():採用del刪除屬性時,觸發

而其又被分爲:

數據描述符:至少實現了__get__()和__set__()

非數據描述符:沒有實現__set__()

class Str(object):
    def __get__(self):
        print("From __get__")

    def __set__(self, instance, value):
        print("From __set__")

    def __delete__(self, instance):
        print("From __delete__")

class People(object):
    name = Str()  ##在其餘類裏面被當作屬性時,纔有被調用,name被Str類代理了
    def __init__(self, name):
        self.name = name

p1 = People("qq")

From __set__  ##觸發了Str類裏面的__set__

注意事項:

  • 描述符自己應該定義成新式類,被代理的類也應該是新式類

  • 必須把描述符定義成這個類的類屬性,不能爲定義到構造函數中

  • 要嚴格遵循該優先級,優先級由高到底分別是

    • 類屬性

    • 數據描述符

    • 實例屬性

    • 非數據描述符

    • 找不到的屬性觸發__getattr__()

property另外用法

一個靜態屬性property本質就是實現了get,set,delete三種方法

class Foo:
    @property
    def AAA(self):
        print('get的時候運行我啊')

    @AAA.setter
    def AAA(self,value):
        print('set的時候運行我啊')

    @AAA.deleter
    def AAA(self):
        print('delete的時候運行我啊')
        
    ##AAA=property(get_AAA,set_AAA,delete_AAA) #內置property三個參數與get,set,delete一一對應

#只有在屬性AAA定義property後才能定義AAA.setter,AAA.deleter
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA

__setitem__,__getitem__,__delitem__

class Foo(object):

    def __getitem__(self, key):
        print('__getitem__', key)

    def __setitem__(self, key, value):
        print('__setitem__', key, value)

    def __delitem__(self, key):
        print('__delitem__', key)

obj = Foo()
##類字典的操做將觸發這些
result = obj['k1']  # 自動觸發執行 __getitem__
obj['k2'] = 'Hermaeus'  # 自動觸發執行 __setitem__
del obj['k1']  # 自動觸發執行 __delitem__

__str__,__repr__,__format__

str函數或者print函數--->obj.__str__()
repr或者交互式解釋器--->obj.__repr__()
若是__str__沒有被定義,那麼就會使用__repr__來代替輸出
注意:這倆方法的返回值必須是字符串,不然拋出異常

formated_time = {
    "YY":"{obj.year}-{obj.month}-{obj.date}",
    "MM":"{obj.year}/{obj.month}/{obj.date}",
    "DD": "{obj.year}:{obj.month}:{obj.date}"
}

class Time(object):
    def __init__(self, year, month, date):
        self.year = year
        self.month = month
        self.date = date

    def __str__(self):
        return "From __str__"

    def __repr__(self):
        return  "From __repr__"

    def __format__(self, format_spec):
        if not format_spec or format_spec not in formated_time.keys():
            format_spec = "DD"
        res_spec = formated_time[format_spec]
        return res_spec.format(obj = self)

try_time = Time(2018, 5, 23)
print(try_time)
print(try_time.__format__("YY"))

From __str__
2018-5-23

__slots__

__slots__是一個類變量,其中變量值能夠是列表,元祖,或者可迭代對象,也能夠是一個字符串(意味着全部實例只有一個數據屬性);使用點來訪問屬性本質就是在訪問類或者對象的__dict__屬性字典(類的字典是共享的,而每一個實例的是獨立的);字典會佔用大量內存,若是你有一個屬性不多的類,可是有不少實例,爲了節省內存可使用__slots__取代實例的__dict__

class Foo(object):
    __slots__ = ["name", "age"]

f1 = Foo()
f1.name = "Hermaeus"
f1.age = 19
print(f1.__dir__())
print(f1.__slots__)

##對象裏面沒有了__dict__,只有了__slots__,這樣有利於減小內存負擔
['__module__', '__slots__', 'age', 'name', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__init__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']  
['name', 'age']

__next__和__iter__實現迭代器協議

##有了__next__和__iter__,即是一個迭代器了
class func(object):
    def __init__(self, x):
        self.x = x

    def __iter__(self):
        return self

    def __next__(self):
        self.x += 1
        return self.x

test_func = func(2)  
print(test_func.__next__())
print(test_func.__next__())
print(test_func.__next__())
print(test_func.__next__())

實現斐波那契數列

class Fib(object):
    def __init__(self):
        self.a = 0
        self.b = 1

    def __iter__(self):
        return self

    def __next__(self):
        self.a , self.b = self.b , self.a + self.b
        return self.a

f1 = Fib()
print(f1.__next__())
print(f1.__next__())
print(f1.__next__())

__doc__,__module__和__class__

class Func(object):
    """  The Infomation of Func"""
    pass
print(Func.__doc__)  ##獲取備註信息

from lib.aa import C
obj = C()
print obj.__module__  ##獲得是那個模塊裏的
print obj.__class__   ##獲得是那個類裏的

The Infomation of Func
lib.aa   即:輸出模塊
lib.aa.C  即:輸出類

__del__

析構方法,當對象在內存中被釋放時,自動觸發執行

class Foo(object):
    def __del__(self):
        print("Over")

f1 = Foo()  ##不過怎麼樣,只要一釋放內存,就會觸發__del__

__enter__和__exit__

」with open(文件) as f「,又叫作上下文管理協議,爲了讓一個對象能使用with語句,必須在對象的類裏面申明__enter和__exit__方法

class MyOpen(object):
    def __init__(self, filename, mode, encoding = "UTF-8"):
        self.filename = filename
        self.mode = mode
        self.encoding = encoding

    def __enter__(self): ##出現with,則觸發__enter__,有返回值就賦予給as申明瞭的變量
        self.f = open(self.filename, self.mode, encoding = self.encoding)
        return self.f

    def __exit__(self, exc_type, exc_val, exc_tb):  ##with執行完以後,觸發__exit__
        self.f.close()  ##exc_type ==>異常類型  exc_val ==>異常值  exc_tb ==>追溯信息
        return True      

    def __getattr__(self, item):  ##避免找不到指定方法而觸發默認的__getattr__
        return self, item

with MyOpen("b.txt", "r") as f:
    print(f.read())

__call__

在對象後面加括號執行

class Foo(object):
    def __call__(self, *args, **kwargs):
        print("Come from __call__")
f1 = Foo()   ##不能直接Foo(),不會執行
f1()

Come from __call__

元類

在Python裏面一切皆對象,那麼類調用的類咱們就叫作元類,那麼默認的元類是type

class Foo(object):
    pass

print(type(Foo))

能夠直接使用type創建新類

##type(name, bases, dict) -> a new type

def __init__(self, name, age):
    self.name = name
    self.age = age

Foo = type("Foo", (object,), {"x":11, "__init__":__init__})
f1 = Foo("Hermaeus", 19)
print(f1.__dict__)

{'name': 'Hermaeus', 'age': 19}

本身創建元類

class MyType(type):
    def __init__(cls, x, y, z):
        print("Runing....")
    def __call__(self, *args, **kwargs):
        obj = self.__new__(self)  ##創建一個空的對象
        self.__init__(obj, *args, **kwargs)  ##從新使用type
        return obj

class Foo(metaclass=MyType):  ## "metaclass="指定元類
    def __init__(self, name):
        self.name = name

f1 = Foo("Hermaeus")
print(f1.name)

Runing....
Hermaeus
相關文章
相關標籤/搜索