文章目录
1 isinstance(obj,cls)和issubclass(sub,super)
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
1 class Foo(object):
2 pass
3
4 obj = Foo()
5
6 isinstance(obj, Foo)------True
issubclass(sub, super)检查sub类是否是 super 类的派生类
1 class Foo(object):
2 pass
3
4 class Bar(Foo):
5 pass
6
7 issubclass(Bar, Foo)------True
2 反射
1 什么是反射
反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。
2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
四个可以实现自省的函数
下列方法适用于类和对象(一切皆对象,类本身也是一个对象)
class BlackMedium:
feature='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_house(self):
print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
def rent_house(self):
print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
b1=BlackMedium('万成置地','回龙观天露园')
#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))
#获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()
# getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊'))
#设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')--->>> def show_name:return self.name+"sb"
print(b1.__dict__)
print(b1.show_name(b1))
#删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错
print(b1.__dict__)
类也是对象
class Foo(object):
staticField = "old boy"
def __init__(self):
self.name = 'wupeiqi'
def func(self):
return 'func'
@staticmethod
def bar():
return 'bar'
print getattr(Foo, 'staticField')
print getattr(Foo, 'func')
print getattr(Foo, 'bar')
导入其他模块,利用反射查找该模块是否存在某个方法
module_test.py
def test():
print('from the test')
当前文件:
index.py
import module_test as obj
print(hasattr(obj,'test'))
getattr(obj,'test')()
反射当前模块成员
import sys
def s1():
print 's1'
def s2():
print 's2'
this_module = sys.modules[__name__] ---->>><module '__main__' from 'D:/LY/newday2/a.py'>
hasattr(this_module, 's1')
getattr(this_module, 's2')
获取当前模块
current_module=__import__(__name__)
current_module----->>module '__main__' from 'D:/LY/newday2/a.py'>
print(current_module.__name__)------>>__main__
x=111
print(hasattr(current_module,"x"))
print(getattr(current_module,"x"))
3 setattr,delattr,getattr
1、getattr
当我们访问一个不存在的属性的时候,会抛出异常,提示我们不存在这个属性。而这个异常就是__getattr__方法抛出的,其原因在于他是访问一个不存在的属性的最后落脚点,作为异常抛出的地方提示出错再适合不过了。
看例子,我们找一个存在的属性和不存在的属性。
class A(object):
def __init__(self, value):
self.value = value
def __getattr__(self, item):
print "into __getattr__"
return "can not find"
a = A(10)
print a.value
# 10
print a.name
# into __getattr__
# can not find
可以看出,访问存在的属性时,会正常返回值,若该值不存在,则会进入最后的兜底函数__getattr__。
2、setattr
在对一个属性设置值的时候,会调用到这个函数,每个设置值的方式都会进入这个方法。
class A(object):
def __init__(self, value):
print "into __init__"
self.value = value
def __setattr__(self, name, value):
print "into __setattr__"
if value == 10:
print "from __init__"
object.__setattr__(self, name, value)
a = A(10)
# into __init__
# into __setattr__
# from __init__
print a.value
# 10
a.value = 100
# into __setattr__
print a.value
# 100
在实例化的时候,会进行初始化,在__init__里,对value的属性值进行了设置,这时候会调用__setattr__方法。
在对a.value重新设置值100的时候,会再次进入__setattr__方法。
需要注意的地方是,在重写__setattr__方法的时候千万不要重复调用造成死循环。
比如:
class A(object):
def __init__(self, value):
self.value = value
def __setattr__(self, name, value):
self.name = value
这是个死循环。当我们实例化这个类的时候,会进入__init__,然后对value进行设置值,设置值会进入__setattr__方法,而__setattr__方法里面又有一个self.name=value设置值的操作,会再次调用自身__setattr__,造成死循环。
除了上面调用object类的__setattr__避开死循环,还可以如下重写__setattr__避开循环。
class A(object):
def __init__(self, value):
self.value = value
def __setattr__(self, name, value):
self.__dict__[name] = value
a = A(10)
print a.value
# 10
3、delattr
__delattr__是个删除属性的方法
class A(object):
def __init__(self, value):
self.value = value
def __delattr__(self, item):
object.__delattr__(self, item)
def __getattr__(self, item):
return "when can not find attribute into __getattr__"
a = A(10)
print a.value
# 10
del a.value
print a.value
# when can not find attribute into __getattr__
delattr__也要避免死循环的问题,就如__setattr__一样,在重写__delattr,避免重复调用。
4 _setitem,__getitem,_delitem
用于索引操作,如字典。以上分别表示获取、设置、删除数据
按照键取类的值
class Foo:
def __init__(self,name):
self.name=name
def __getitem__(self, item):
print(self.__dict__[item])
def __setitem__(self, key, value):
self.__dict__[key]=value
def __delitem__(self, key):
print('del obj[key]时,我执行')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key时,我执行')
self.__dict__.pop(item)
f1=Foo('sb')
f1['age']=18
f1['age1']=19
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__)
# -*- coding:utf-8 -*-
class Foo(object):
def __getitem__(self, key):
print('__getitem__', key)
def __setitem__(self, key, value):
print('__setitem__', key, value)
def __delitem__(self, key):
print('__delitem__', key)
obj = Foo()
result = obj['k1'] # 自动触发执行 __getitem__
obj['k2'] = 'laowang' # 自动触发执行 __setitem__
del obj['k1'] # 自动触发执行 __delitem__
5__getslice__、setslice、delslice
该三个方法用于分片操作,如:列表
# -*- coding:utf-8 -*-
class Foo(object):
def __getslice__(self, i, j):
print('__getslice__', i, j)
def __setslice__(self, i, j, sequence):
print('__setslice__', i, j)
def __delslice__(self, i, j):
print('__delslice__', i, j)
obj = Foo()
obj[-1:1] # 自动触发执行 __getslice__
obj[0:1] = [11,22,33,44] # 自动触发执行 __setslice__
del obj[0:2] # 自动触发执行 __delslice__
getslice、setslice、delslice:分别用于分片操作,如列表的切片
魔法属性(只限python2.x版本,python3.x无此功能):
案例:
# coding=utf-8
class Foo(object):
save_list = [1, 2, 3, 4, 5, 6, 34, 23, 5]
def __getslice__(self, i, j):
print "__getslice__:"
return self.save_list[i: j]
def __setslice__(self, i, j, sequence):
print "__setslice__:"
self.save_list[i:j] = sequence
print self.save_list
def __delslice__(self, i, j):
print "__delslice__:"
del self.save_list[i: j]
print self.save_list
obj = Foo()
result = obj[1: 2]
print(result)
obj[0: 1] = [23, 22, 15, 4]
del obj[4:]
"""
结果:
__getslice__:
[2]
__setslice__:
[23, 22, 15, 4, 2, 3, 4, 5, 6, 34, 23, 5]
__delslice__:
[23, 22, 15, 4]
"""