反射

一、反射的概念

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'

 

posted @ 2018-01-22 20:26  人生不如戏  阅读(507)  评论(0编辑  收藏  举报