面向物件【day08】:類的起源與metaclass(二)
本節內容
1、概述
2、類的起源
3、__new__方法
4、__metaclass__方法
一、概述
前面我們學習了大篇幅的關於類,通過類建立物件,那我們想知道這個類到底是怎麼產生的呢?它的一切來源是什麼?還有物件,物件是通過什麼方法建立的,現在我們一頭霧水,行的,下面我們就來揭開類的面紗,看看類和物件到底是怎麼建立的,通過什麼建立的。
二、類的起源
2.1 傳統建立類
1 2 3 4 5 |
class
Foo(
object
):
def
__init__(
self
,name):
self
.name
=
name
f
=
Foo(
"shuaigaogao"
)
|
f 是通過 Foo 類例項化的物件,其實,不僅 f 是一個物件,Foo類本身也是一個物件,因為在Python中一切事物都是物件,
1 2 |
print
(
type
(f))
#輸出:<class '__main__.Foo'> 表示:f 物件由Foo類建立
print
(
type
(Foo))
#輸出:<class 'type'> 表示:Foo類物件由 type 類建立
|
所以,f物件是Foo類的一個例項,Foo類物件是 type 類的一個例項,即:Foo類物件 是通過type類的構造方法建立
2.2 type建立類
說明: type建立類的格式,類名 = type('類名',(父類,),{'方法名':方法的記憶體地址})
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def
func(
self
):
#建立方法
print
(
"hello {0}"
.
format
(
self
.name))
def
__init__(
self
,name):
#建立構造方法
self
.name
=
name
#通過type建立類,如果是經典類的話則寫成:Foo = type("Foo",(),{"talk":func,"__init__":__init__})
Foo
=
type
(
"Foo"
,(
object
,),{
"talk"
:func,
"__init__"
:__init__})
f
=
Foo(
"shuaigaogao"
)
#建立物件
f.talk()
#輸出
hello shuaigaogao
|
總結:類 是由 type 類 例項化產生的
值得注意的是,新式類的寫法,在繼承父類那邊,你繼承一個父類後面就要加一個逗號,加逗號,它就把它當做一個元組,不加逗號,就是一個值了
三、__new__方法
3.1 概念
new方法是類自帶的一個方法,可以重構,__new__方法在例項化的時候也會執行,並且先於__init__方法之前執行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class
Foo(
object
):
def
__init__(
self
,name):
self
.name
=
name
print
(
"Foo __init__"
)
def
__new__(
cls
,
*
args,
*
*
kwargs):
print
(
"Foo __new__"
,
cls
,
*
args,
*
*
kwargs)
return
object
.__new__(
cls
)
f
=
Foo(
"shuaigaogao"
)
#輸出
Foo __new__ <
class
'__main__.Foo'
> shuaigaogao
#執行了new方法
Foo __init__
#執行了__init__方法
|
3.2 new方法作用
作用:所有物件都是通過new方法來例項化的,new裡面呼叫了init方法,所以在例項化的過程中先執行的是new方法,而不是init方法。
①重構__new__方法
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class
Foo(
object
):
def
__init__(
self
,name):
self
.name
=
name
print
(
"Foo __init__"
)
def
__new__(
cls
,
*
args,
*
*
kwargs):
print
(
"Foo __new__"
,
cls
,
*
args,
*
*
kwargs)
f
=
Foo(
"shuaigaogao"
)
#例項化
#輸出
Foo __new__ <
class
'__main__.Foo'
> shuaigaogao
|
由上面的例子看出,沒有執行__init__方法
②重構__new__方法,並繼承父類的__new__方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class
Foo(
object
):
def
__init__(
self
,name):
self
.name
=
name
print
(
"Foo __init__"
)
def
__new__(
cls
,
*
args,
*
*
kwargs):
#cls相當於傳入類Foo
print
(
"Foo __new__"
,
cls
,
*
args,
*
*
kwargs)
return
object
.__new__(
cls
)
#繼承父類的__new__方法,這邊必須以返回值的形式繼承
f
=
Foo(
"shuaigaogao"
)
#輸出
Foo __new__ <
class
'__main__.Foo'
> shuaigaogao
Foo __init__
|
由上面不難看出,大多數情況下,你都不要去重構你的__new__方法,因為你父類中已經有__new__方法了,已經幫你寫好了怎麼去建立類,如果你重寫的話,就會覆蓋父類的裡面的__new__方法。但是你重構可以增加一點小功能,但是你覆蓋了以後還是需要繼承父類回來,要不然你的這個實力就建立不了。
3.3 使用場景
我想對我自己寫的一些類進行定製,就在它例項化之前就進行定製,就可以用到__new__方法,new方法就是用來建立實力的,重構new方法,必須以返回值的形式繼承父類的new方法。
①需求:我在建立物件時候,同時建立一個類變數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class
Foo(
object
):
def
__init__(
self
,name):
self
.name
=
name
print
(
"Foo __init__"
)
def
__new__(
cls
,
*
args,
*
*
kwargs):
#cls相當於是傳入的類名Foo
cls
.name
=
"shuaigaogao"
#建立物件是定義靜態變數
print
(
cls
.name)
return
object
.__new__(
cls
)
#繼承父類的__new__方法
f
=
Foo(
"shuaigaogao"
)
print
(Foo.name)
#輸出
shuaigaogao
Foo __init__
shuaigaogao
|
四、__metaclass__方法
4.1 metaclass作用
metaclass這個屬性叫做元類,它是用來表示這個類是由誰來幫他例項化建立的,說白了,就是相當於自己定製一個類,就這麼一個意思。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
class
MyType(
type
):
def
__init__(
self
,
*
args,
*
*
kwargs):
print
(
"Mytype __init__"
,
*
args,
*
*
kwargs)
def
__call__(
self
,
*
args,
*
*
kwargs):
print
(
"Mytype __call__"
,
*
args,
*
*
kwargs)
obj
=
self
.__new__(
self
)
print
(
"obj "
,obj,
*
args,
*
*
kwargs)
print
(
self
)
self
.__init__(obj,
*
args,
*
*
kwargs)
return
obj
def
__new__(
cls
,
*
args,
*
*
kwargs):
print
(
"Mytype __new__"
,
*
args,
*
*
kwargs)
return
type
.__new__(
cls
,
*
args,
*
*
kwargs)
class
Foo(
object
,metaclass
=
MyType):
#python3統一用這種
#__metaclass__ = MyType #python2.7中的寫法
def
__init__(
self
,name):
self
.name
=
name
print
(
"Foo __init__"
)
def
__new__(
cls
,
*
args,
*
*
kwargs):
print
(
"Foo __new__"
,
cls
,
*
args,
*
*
kwargs)
return
object
.__new__(
cls
)
f
=
Foo(
"shuaigaogao"
)
print
(
"f"
,f)
print
(
"fname"
,f.name)
#輸出
Mytype __new__ Foo (<
class
'object'
>,) {
'__new__'
: <function Foo.__new__ at
0x0000025EF0EFD6A8
>,
'__init__'
: <function Foo.__init__ at
0x0000025EF0EFD620
>,
'__qualname__'
:
'Foo'
,
'__module__'
:
'__main__'
}
Mytype __init__ Foo (<
class
'object'
>,) {
'__new__'
: <function Foo.__new__ at
0x0000025EF0EFD6A8
>,
'__init__'
: <function Foo.__init__ at
0x0000025EF0EFD620
>,
'__qualname__'
:
'Foo'
,
'__module__'
:
'__main__'
}
Mytype __call__ shuaigaogao
Foo __new__ <
class
'__main__.Foo'
>
obj <__main__.Foo
object
at
0x0000025EF0F05048
> shuaigaogao
<
class
'__main__.Foo'
>
Foo __init__
f <__main__.Foo
object
at
0x0000025EF0F05048
>
fname shuaigaogao
|
建立過程如下:
4.2 執行順序
類的生成 呼叫 順序依次是 __new__ --> __init__ --> __call__
metaclass 詳解文章:猛擊這裡 得票最高那個答案寫的非常好
作者:羅阿紅 出處:http://www.cnblogs.com/luoahong/ 本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線。本節內容
1、概述
2、類的起源
3、__new__方法
4、__metaclass__方法
一、概述
前面我們學習了大篇幅的關於類,通過類建立物件,那我們想知道這個類到底是怎麼產生的呢?它的一切來源是什麼?還有物件,物件是通過什麼方法建立的,現在我們一頭霧水,行的,下面我們就來揭開類的面紗,看看類和物件到底是怎麼建立的,通過什麼建立的。
二、類的起源
2.1 傳統建立類
1 2 3 4 5 |
class
Foo(
object
):
def
__init__(
self
,name):
self
.name
=
name
f
=
Foo(
"shuaigaogao"
)
|
f 是通過 Foo 類例項化的物件,其實,不僅 f 是一個物件,Foo類本身也是一個物件,因為在Python中一切事物都是物件,按照一切事物都是物件的理論:obj物件是通過執行Foo類的構造方法建立,那麼Foo類物件應該也是通過執行某個類的 構造方法 建立。
1 2 |
print
(
type
(f))
#輸出:<class '__main__.Foo'> 表示:f 物件由Foo類建立
print
(
type
(Foo))
#輸出:<class 'type'> 表示:Foo類物件由 type 類建立
|
所以,f物件是Foo類的一個例項,Foo類物件是 type 類的一個例項,即:Foo類物件 是通過type類的構造方法建立
2.2 type建立類
說明: type建立類的格式,類名 = type('類名',(父類,),{'方法名':方法的記憶體地址})
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def
func(
self
):
#建立方法
print
(
"hello {0}"
.
format
(
self
.name))
def
__init__(
self
,name):
#建立構造方法
self
.name
=
name
#通過type建立類,如果是經典類的話則寫成:Foo = type("Foo",(),{"talk":func,"__init__":__init__})
Foo
=
type
(
"Foo"
,(
objec
|