Python反射与自省学习

1.反射自省的概念

自省:自省就是能够获得自身的结构和方法,给开发者可以灵活的调用,给定一个对象,返回该对象的所有属性和函数列表,或给定对象和该对象的函数或者属性的名字,返回对象的函数或者属性实例。
反射就是通过字字符串的形式来操作对象或者模块的成员,一种基于字符串的事件驱动。

2.类与属性

类是对象的定义,而实例是真正的实物,它存放了类中所定义的对象的具体信息
类是现实世界的抽象的实体以编程形式出现,实例是这些对象的具体化
类属性:属性就是一个对象的数据或者函数元素

class MyNewClass: #所有的类需要至少一个继承,object是所有类的父类
    'define my new class for test' #类的文档,不能被子类继承,可以使用__doc__调出
    version = '1.0'  #类的数据属性
    def __init__(self):  #类似构造器,创建一个新对象时调用,self代表实例对象本身,调用方法时,解释器传给方法
        print('create a object')
    def in_class(self):  #方法,必须绑定到实例才能调用
        print('in class ')
    #申明与定义类同时进行  
myclass = MyNewClass() #实例化
create a object
MyNewClass.version  #访问类数据属性
'1.0'
myclass.version  #访问实例属性
'1.0'
MyNewClass.in_class()  #通过类不能调用方法
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-7-5c59b2c4c0c8> in <module>()
----> 1 MyNewClass.in_class()  #通过类不能调用方法


TypeError: in_class() missing 1 required positional argument: 'self'
myclass.in_class()  #通过实例进行方法调用
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)  #子类实例化
create a sub class 
my_sub_class.num_is()   #子类方法调用
The num is 123
my_sub_class.in_class()  #访问父类方法
in class 
my_sub_class.version  #子类数据属性
'2.0'

dir()方法,没有参数,返回当前本地作用域中的名称列表。使用参数,尝试返回该对象的有效属性列表

dir(MyNewClass)   #通过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__用于存储对象(可写)属性的字典或其他映射对象,不是所有的对象都有__dict__属性。例如,如果你在一个类中添加了 __slots__属性,那么这个类的实例将不会拥有 __dict__ 属性,但是 dir() 仍然可以找到并列出它的实例所有有效属性

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.实例与实例属性

如果说类是一种很数据结构定义类型,那么实例就是申明了这种类型的变量

__init__()构造器是最早可以设置实例属性的地方

class  MyClass (object):
        pass


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

如果定义了构造器,它不应返回任何对象,因为实例对象是自动在实例化调用后返回的。
__init__()就不应该返回任何对象,否则,就可能出现冲突,因为只能返回实例。

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

实例属性

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)   #实例属性
['__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

类属性和实例属性:类属性仅是与类相关的数据值,这些值可以像静态成员那样被引用,即使在多次实例化中调用类,他们的值都保持不变

class T(object):
    version = 1.0
t = T()  #实例化
T.version  #访问类属性
1.0
t.version  #访问实例属性
1.0
t.version = 2.0  #改变实例属性(实际上时床架了新的实例属性),而非类属性
t.version
2.0
T.version   #类属性没有改变
1.0
del t.version  #删除实例属性, 给一个与类属性同名的实例属性赋值,我们会有效的“隐藏”类属性,删除又重现
t.version
1.0
T.version = 3.0  #更新类属性
t.version   #实例访问,其值已经改变
3.0

但是在类属性可以改变的情况下,类属性可以通过实例改变

class Foo(object):
     x = {2003: 'poe2'}
foo = Foo()
foo.x
{2003: 'poe2'}
foo.x[2004] = 'valid path'   #通过实例改变
foo.x
{2003: 'poe2', 2004: 'valid path'}
Foo.x   #类属性已经改变
{2003: 'poe2', 2004: 'valid path'}

3.绑定和方法调用

方法仅仅是类内部定义的函数,这意味着方法时类属性而不是实例属性
任何方法定义的第一个参数都是变量self,它表示调用此方法的实例对象

非绑定方法:需要调用一个还没有任何实例的类中的一个方法

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'))  #未绑定的方法必须使用一个Person实例作为第一个参数来调用
'The name is zhang'
p = Person('python')  #实例化绑定方法,使用实例调用,调用的实例被作为第一个参数被隐含的传递过去
print(p)
<__main__.Person object at 0x7fd26c505ac8>

4.内建函数

hasattr、getattr、setattr、delattr:对象是否有、取得、设置、删除某个属性

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的值,但是对象没有该值,抛出异常
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-80-f6c57b29833a> in <module>()
----> 1 getattr(ta, 'bar')  #取得bar的值,但是对象没有该值,抛出异常


AttributeError: 'TestAttr' object has no attribute 'bar'
setattr(ta, 'bar', 100000)  #设置某个值
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')  #删除某个值
delattr(ta, 'foo')
ta.__dict__
{'my attr': 'Python Class Attr Function'}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • 要点: 函数式编程:注意不是“函数编程”,多了一个“式” 模块:如何使用模块 面向对象编程:面向对象的概念、属性、...
    victorsungo阅读 1,459评论 0 6
  • Python进阶框架 希望大家喜欢,点赞哦首先感谢廖雪峰老师对于该课程的讲解 一、函数式编程 1.1 函数式编程简...
    Gaolex阅读 5,486评论 6 53
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,849评论 6 13
  • 定义类并创建实例 在Python中,类通过 class 关键字定义。以 Person 为例,定义一个Person类...
    绩重KF阅读 3,923评论 0 13
  • “知床斜里町车站,10:43到,10:58出发,停车15分钟“,列车司机用手仔细地滑过右上角的白纸写的时刻表小声地...
    80天旅行阅读 413评论 0 1