前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

反射

作者头像
人生不如戏
发布2018-04-12 11:34:41
7120
发布2018-04-12 11:34:41
举报
文章被收录于专栏:抠抠空间抠抠空间

一、反射的概念

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

四个可以实现自省的函数

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

二、反射的四种方法

只要能通过 xx.xx 调用到的东西都可以用反射,如:

# 类.属性
# 类.方法
# 对象.属性
# 对象.方法
# 内置模块.属性
# 自定义模块.属性
# 模块.类

①hasattr

此方法是用来检查一个对象有没有一个XX,格式为:hansattr(对象,‘XX‘),注意,第二个参数是一个字符串类型的。返回一个布尔值,如下:

 1 class Person:
 2     kind = '人类'
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6         self.changdu = 28
 7     def func(self):
 8         print('func.....')
 9 p = Person('fuyong',18)
10 
11 print(hasattr(p,'name'))        #True
12 print(hasattr(p,'func'))        #True
13 print(hasattr(Person,'kind'))   #True
14 print(hasattr(Person,'func'))   #True

②getattr

此方法是用来获取一个对象的XX,XX是字符串类型,它可以是类的属性,可以对象是属性及方法,可以是模块的类,等等……

最好搭配hasattr方法使用,判断它有此方法或者对象的时候才获取,以免找不到报错,也可以指定找不到的默认值。格式为getattr(对象,XX,默认值),如下:

 1 class Person:
 2     kind = '人类'
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6         self.changdu = 28
 7     def func(self):
 8         print('func.....')
 9 p = Person('fuyong',18)
10 
11 ret = getattr(p,'func',None)
12 if ret:
13    ret()    #func.....
14 
15 ret = getattr(p,'funcxxx','没有此方法')
16 print(ret)  #没有此方法
17 
18 if hasattr(p,'func'):
19     getattr(p,'func')() #func.....

③setattr

此方法用来设置一个对象的属性,格式为setattr(对象,属性名,属性值) ,如下:

 1 class Person:
 2     kind = '人类'
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6         self.changdu = 28
 7     def func(self):
 8         print('func.....')
 9 p = Person('fuyong',18)
10 
11 print(p.age)        #18
12 setattr(p,'age',19)
13 print(p.age)        #19
14     

④delattr

此方法是用来删除一个对象的属性,格式为delattr(对象,XXX) ,如下:

 1 class Person:
 2     kind = '人类'
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6         self.changdu = 28
 7     def func(self):
 8         print('func.....')
 9 p = Person('fuyong',18)
10 
11 print(p.age)        #18
12 delattr(p,'age')
13 print(p.age)        #报错:AttributeError: 'Person' object has no attribute 'age'

三、类的内置方法

① __init__

此方法在类被实例化的时候被自动调用

② __str__和__repr__

__str__( )方法在三种情况下被自动调用

△ str(对象名)

△ print(对象名)

△ '%s'%对象名

如下:

 1 class Person:
 2     def __init__(self,name,age):
 3         self.name = name
 4         self.age = age
 5     def __str__(self):
 6         return '他是一个名叫%s的帅哥'%self.name
 7 
 8 p = Person('fuyong',18)
 9 print(str(p))           #他是一个名叫fuyong的帅哥
10 print(p)                #他是一个名叫fuyong的帅哥
11 print('%s'%p)           #他是一个名叫fuyong的帅哥

__repr__方法在以下三种情况下被调用:

△ repr(对象名)

△ '%r'%对象名

△ 当类没有__str__方法又被调用__str__方法的时候被调用

如下:

 1 class Person:
 2     def __init__(self,name,age):
 3         self.name = name
 4         self.age = age
 5     def __repr__(self):
 6         return '他是一个名叫%s的帅哥'%self.name
 7 
 8 p = Person('fuyong',18)
 9 print(repr(p))
10 print('%r'%p)
11 print(str(p))
12 print(p)
13 #打印结果如下
14 # 他是一个名叫fuyong的帅哥
15 # 他是一个名叫fuyong的帅哥
16 # 他是一个名叫fuyong的帅哥
17 # 他是一个名叫fuyong的帅哥

③ __del__

此方法会在对象被释放的时候被自动调用(一种情况是对象被删除,一种情况是程序执行完了被Python解释器释放),如下:

 1 class Person:
 2     def __init__(self,name,age):
 3         self.name = name
 4         self.age = age
 5     def __del__(self):
 6         print('程序执行完了')
 7 
 8 p = Person('fuyong',18)
 9 
10 #程序执行完了

④ __call__

此方法会在对象后面加括号的时候被自动调用,如下:

1 class Person:
2     def __init__(self,name,age):
3         self.name = name
4         self.age = age
5     def __call__(self):
6         print('你在对象名后加了括号(类似一个函数)')
7 p = Person('fuyong',18)
8 p()
9 #你在对象名后加了括号(类似一个函数)

⑤ __len__

此方法在调用len(对象)的时候被执行,如下:

1 class Person:
2     def __init__(self,name,age):
3         self.name = name
4         self.age = age
5         self.changdu = 28
6     def __len__(self):
7         return self.changdu
8 p = Person('fuyong',18)
9 print(len(p)) #28

⑥ __new__

此方法是在实例化一个对象的时候回自动触发(在__init__函数之前)。如下:

 1 class Person:
 2     def __init__(self,name):
 3         self.name = name
 4         print('调用__init__函数........')
 5 
 6     def __new__(cls, *args, **kwargs):
 7         print('调用__new__函数.........')
 8         return object.__new__(Person)
 9 
10 p = Person('付勇')
11 print(p.name)
12 
13 #调用__new__函数.........
14 # 调用__init__函数........
15 # 付勇

利用__new__方法实现单例模式:

 1 class Person:
 2     _obj = None
 3     def __init__(self,name):
 4         self.name = name
 5 
 6     def __new__(cls, *args, **kwargs):
 7         if cls._obj:
 8             return _obj
 9         else:
10             _obj = object.__new__(Person)
11 
12 p1 = Person('付勇')
13 p2 = Person('小明')
14 print(p1 is p2)

⑦ __hash__

此方法在has(对象)的时候被调用,如下:

 1 class Person:
 2     _obj = None
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6 
 7     def __hash__(self):
 8         return hash(self.name)+hash(self.age)
 9 
10 p1 = Person('付勇',18)
11 p2 = Person('付勇',19)
12 print(hash(p1) == hash(p2))         #False

⑧__eq__

此方法在比较两个对象的时候被调用,如:obj1 == obj2  或者   如下:

 1 class Person:
 2     _obj = None
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6 
 7     def __eq__(self, other):
 8         if self.__dict__ == other.__dict__:
 9             return True
10         else:
11             return False
12 
13 p1 = Person('付勇',18)
14 p2 = Person('付勇',18)
15 print(p1 == p2)         #True

⑨ __getitem__\__setitem__\__delitem__

一旦一个类中定义了这三种内置方法,操作类的属性的时候就可以像操作字典一样,如:

obj [属性]                 ---->   __getitem__

obj [属性] = 属性值         ----> __setitem__

del obj [属性]             ---->  __delitem__

  实例如下:

 1 class Person:
 2     def __init__(self,name,age):
 3         self.name = name
 4         self.age = age
 5 
 6     def __getitem__(self, item):
 7         return self.__dict__[item]
 8 
 9     def __setitem__(self, key, value):
10         self.__dict__[key] = value
11 
12     def __delitem__(self,key):
13         del self.__dict__[key]
14 
15 p = Person('付勇',18)
16 
17 print(p['name'])      #付勇
18 
19 p['age'] = 19
20 print(p['age'])      #19
21 
22 del p['age']
23
24 print(p['age'])     #因为age属性已被删除,所以会报错!KeyError: 'age'
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-01-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、反射的概念
  • 二、反射的四种方法
    • ①hasattr
      • ②getattr
        • ③setattr
          • ④delattr
          • 三、类的内置方法
            • ① __init__
              • ② __str__和__repr__
                • ③ __del__
                  • ④ __call__
                    • ⑤ __len__
                      • ⑥ __new__
                        • ⑦ __hash__
                          • ⑧__eq__
                            • ⑨ __getitem__\__setitem__\__delitem__
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档