Python反射與自省學(xué)習(xí)

1.反射自省的概念

自?。鹤允【褪悄軌颢@得自身的結(jié)構(gòu)和方法,給開(kāi)發(fā)者可以靈活的調(diào)用,給定一個(gè)對(duì)象,返回該對(duì)象的所有屬性和函數(shù)列表,或給定對(duì)象和該對(duì)象的函數(shù)或者屬性的名字,返回對(duì)象的函數(shù)或者屬性實(shí)例。
反射就是通過(guò)字字符串的形式來(lái)操作對(duì)象或者模塊的成員,一種基于字符串的事件驅(qū)動(dòng)。

2.類與屬性

類是對(duì)象的定義,而實(shí)例是真正的實(shí)物,它存放了類中所定義的對(duì)象的具體信息
類是現(xiàn)實(shí)世界的抽象的實(shí)體以編程形式出現(xiàn),實(shí)例是這些對(duì)象的具體化
類屬性:屬性就是一個(gè)對(duì)象的數(shù)據(jù)或者函數(shù)元素

class MyNewClass: #所有的類需要至少一個(gè)繼承,object是所有類的父類
    'define my new class for test' #類的文檔,不能被子類繼承,可以使用__doc__調(diào)出
    version = '1.0'  #類的數(shù)據(jù)屬性
    def __init__(self):  #類似構(gòu)造器,創(chuàng)建一個(gè)新對(duì)象時(shí)調(diào)用,self代表實(shí)例對(duì)象本身,調(diào)用方法時(shí),解釋器傳給方法
        print('create a object')
    def in_class(self):  #方法,必須綁定到實(shí)例才能調(diào)用
        print('in class ')
    #申明與定義類同時(shí)進(jìn)行  
myclass = MyNewClass() #實(shí)例化
create a object
MyNewClass.version  #訪問(wèn)類數(shù)據(jù)屬性
'1.0'
myclass.version  #訪問(wèn)實(shí)例屬性
'1.0'
MyNewClass.in_class()  #通過(guò)類不能調(diào)用方法
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-7-5c59b2c4c0c8> in <module>()
----> 1 MyNewClass.in_class()  #通過(guò)類不能調(diào)用方法


TypeError: in_class() missing 1 required positional argument: 'self'
myclass.in_class()  #通過(guò)實(shí)例進(jìn)行方法調(diào)用
in class 
class MySubClass(MyNewClass):
    'This is my second Class for test'   #文檔不能被子類繼承
    version = '2.0'
    def __init__(self, num):   #重寫__init__方法
        self.num = num
        print('create a sub class ')
    def num_is(self):         #為子類增加方法
        print('The num is %d' % self.num)
my_sub_class = MySubClass(123)  #子類實(shí)例化
create a sub class 
my_sub_class.num_is()   #子類方法調(diào)用
The num is 123
my_sub_class.in_class()  #訪問(wèn)父類方法
in class 
my_sub_class.version  #子類數(shù)據(jù)屬性
'2.0'

dir()方法,沒(méi)有參數(shù),返回當(dāng)前本地作用域中的名稱列表。使用參數(shù),嘗試返回該對(duì)象的有效屬性列表

dir(MyNewClass)   #通過(guò)dir()可以查看類的屬性
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'in_class',
 'version']

object.__dict__用于存儲(chǔ)對(duì)象(可寫)屬性的字典或其他映射對(duì)象,不是所有的對(duì)象都有__dict__屬性。例如,如果你在一個(gè)類中添加了 __slots__屬性,那么這個(gè)類的實(shí)例將不會(huì)擁有 __dict__ 屬性,但是 dir() 仍然可以找到并列出它的實(shí)例所有有效屬性

MyNewClass.__dict__  #類的屬性
mappingproxy({'__dict__': <attribute '__dict__' of 'MyNewClass' objects>,
              '__doc__': 'define my new class for test',
              '__init__': <function __main__.MyNewClass.__init__>,
              '__module__': '__main__',
              '__weakref__': <attribute '__weakref__' of 'MyNewClass' objects>,
              'in_class': <function __main__.MyNewClass.in_class>,
              'version': '1.0'})
MyNewClass.__name__   #類名
'MyNewClass'
MyNewClass.__doc__    #查看文檔
'define my new class for test'
MySubClass.__doc__
'This is my second Class for test'
MySubClass.__bases__     #查看類的父類的元組
(__main__.MyNewClass,)
MyNewClass.__bases__
(object,)
MyNewClass.__module__   #類定義所在的模塊
'__main__'
 MyNewClass.__class__
type

2.實(shí)例與實(shí)例屬性

如果說(shuō)類是一種很數(shù)據(jù)結(jié)構(gòu)定義類型,那么實(shí)例就是申明了這種類型的變量

__init__()構(gòu)造器是最早可以設(shè)置實(shí)例屬性的地方

class  MyClass (object):
        pass


mc = MyClass()
mc
<__main__.MyClass at 0x7fd26c503198>

如果定義了構(gòu)造器,它不應(yīng)返回任何對(duì)象,因?yàn)閷?shí)例對(duì)象是自動(dòng)在實(shí)例化調(diào)用后返回的。
__init__()就不應(yīng)該返回任何對(duì)象,否則,就可能出現(xiàn)沖突,因?yàn)橹荒芊祷貙?shí)例。

class MyClass(object):
    def __init__(self):
        print('Initialized')
    return 1

mc = MyClass()
  File "<ipython-input-29-8544d6773fc1>", line 4
    return 1
    ^
SyntaxError: 'return' outside function

實(shí)例屬性

class C:
    pass
c = C()
c.foo = 'foo foo'
c.bar = 'bar bar'
dir(C)  #類屬性
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']
dir(c)   #實(shí)例屬性
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'bar',
 'foo']
c.__dict__ 
{'bar': 'bar bar', 'foo': 'foo foo'}
class T:
    pass
t = T()
t.__dict__
{}
t.__class__
__main__.T

類屬性和實(shí)例屬性:類屬性僅是與類相關(guān)的數(shù)據(jù)值,這些值可以像靜態(tài)成員那樣被引用,即使在多次實(shí)例化中調(diào)用類,他們的值都保持不變

class T(object):
    version = 1.0
t = T()  #實(shí)例化
T.version  #訪問(wèn)類屬性
1.0
t.version  #訪問(wèn)實(shí)例屬性
1.0
t.version = 2.0  #改變實(shí)例屬性(實(shí)際上時(shí)床架了新的實(shí)例屬性),而非類屬性
t.version
2.0
T.version   #類屬性沒(méi)有改變
1.0
del t.version  #刪除實(shí)例屬性, 給一個(gè)與類屬性同名的實(shí)例屬性賦值,我們會(huì)有效的“隱藏”類屬性,刪除又重現(xiàn)
t.version
1.0
T.version = 3.0  #更新類屬性
t.version   #實(shí)例訪問(wèn),其值已經(jīng)改變
3.0

但是在類屬性可以改變的情況下,類屬性可以通過(guò)實(shí)例改變

class Foo(object):
     x = {2003: 'poe2'}
foo = Foo()
foo.x
{2003: 'poe2'}
foo.x[2004] = 'valid path'   #通過(guò)實(shí)例改變
foo.x
{2003: 'poe2', 2004: 'valid path'}
Foo.x   #類屬性已經(jīng)改變
{2003: 'poe2', 2004: 'valid path'}

3.綁定和方法調(diào)用

方法僅僅是類內(nèi)部定義的函數(shù),這意味著方法時(shí)類屬性而不是實(shí)例屬性
任何方法定義的第一個(gè)參數(shù)都是變量self,它表示調(diào)用此方法的實(shí)例對(duì)象

非綁定方法:需要調(diào)用一個(gè)還沒(méi)有任何實(shí)例的類中的一個(gè)方法

class Person(object):
    def __init__(self, name):
        self.name = name
    def get_name(self):
        return('The name is %s' % self.name)
Person.get_name
<function __main__.Person.get_name>
Person.get_name()   #方法未綁定
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-66-257ab8eff3fa> in <module>()
----> 1 Person.get_name()   #方法未綁定


TypeError: get_name() missing 1 required positional argument: 'self'
Person.get_name(Person('zhang'))  #未綁定的方法必須使用一個(gè)Person實(shí)例作為第一個(gè)參數(shù)來(lái)調(diào)用
'The name is zhang'
p = Person('python')  #實(shí)例化綁定方法,使用實(shí)例調(diào)用,調(diào)用的實(shí)例被作為第一個(gè)參數(shù)被隱含的傳遞過(guò)去
print(p)
<__main__.Person object at 0x7fd26c505ac8>

4.內(nèi)建函數(shù)

hasattr、getattr、setattr、delattr:對(duì)象是否有、取得、設(shè)置、刪除某個(gè)屬性

class TestAttr(object):
    def __init__(self):
        self.foo = 100
ta = TestAttr()
hasattr(ta, 'foo')  #判斷是否具有'foo'屬性
True
getattr(ta, 'foo')  #取得foo的值
100
getattr(ta, 'bar')  #取得bar的值,但是對(duì)象沒(méi)有該值,拋出異常
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-80-f6c57b29833a> in <module>()
----> 1 getattr(ta, 'bar')  #取得bar的值,但是對(duì)象沒(méi)有該值,拋出異常


AttributeError: 'TestAttr' object has no attribute 'bar'
setattr(ta, 'bar', 100000)  #設(shè)置某個(gè)值
getattr(ta, 'bar')
100000
setattr(ta, 'my attr', 'Python Class Attr Function')
dir(ta)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'bar',
 'foo',
 'my attr']
delattr(ta, 'bar')  #刪除某個(gè)值
delattr(ta, 'foo')
ta.__dict__
{'my attr': 'Python Class Attr Function'}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 要點(diǎn): 函數(shù)式編程:注意不是“函數(shù)編程”,多了一個(gè)“式” 模塊:如何使用模塊 面向?qū)ο缶幊蹋好嫦驅(qū)ο蟮母拍?、屬性?..
    victorsungo閱讀 1,695評(píng)論 0 6
  • Python進(jìn)階框架 希望大家喜歡,點(diǎn)贊哦首先感謝廖雪峰老師對(duì)于該課程的講解 一、函數(shù)式編程 1.1 函數(shù)式編程簡(jiǎn)...
    Gaolex閱讀 5,986評(píng)論 6 53
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 12,368評(píng)論 6 13
  • 定義類并創(chuàng)建實(shí)例 在Python中,類通過(guò) class 關(guān)鍵字定義。以 Person 為例,定義一個(gè)Person類...
    績(jī)重KF閱讀 4,100評(píng)論 0 13
  • “知床斜里町車站,10:43到,10:58出發(fā),停車15分鐘“,列車司機(jī)用手仔細(xì)地滑過(guò)右上角的白紙寫的時(shí)刻表小聲地...
    80天旅行閱讀 497評(píng)論 0 1

友情鏈接更多精彩內(nèi)容