动态解释
例1
定义三个功能类似的类:初始化名字,并有一个打印职业和名字的方法
测试文件:
写一个测试方法who_am_i
输出结果:
例2
Python提供了open()函数来打开一个磁盘文件,并返回 File 对象。File对象有一个read()方法可以读取文件内容:
例如,从文件读取内容并解析为JSON结果:
Python提供了open()函数来打开一个磁盘文件,并返回 File 对象。File对象有一个read()方法可以读取文件内容:
例如,从文件读取内容并解析为JSON结果:
importjson
f= open('/path/to/file.json', 'r')print json.load(f)
由于Python的动态特性,json.load()并不一定要从一个File对象读取内容。任何对象,只要有read()方法,就称为File-like Object,都可以传给json.load()。
请尝试编写一个File-like Object,把一个字符串 r'["Tim", "Bob", "Alice"]'包装成 File-like Object 并由 json.load() 解析。
importjsonclassStudents(object):defread(self):return r'["Tim", "Bob", "Alice"]'s=Students()printjson.load(s)
[u'Tim', u'Bob', u'Alice']
动态绑定属性
定义两个类做比较,一个定义了_slots_,另一个没有
classPlayer1(object):"""docstring for Player1"""
def __init__(self, uid, name, status = 0, level = 1):
self.uid=uid
self.name=name
self.status=status
self.level=levelclassPlayer2(object):"""docstring for Player2"""
__slots__ = ['uid', 'name', 'status', 'level']def __init__(self, uid, name, status = 0, level = 1):
self.uid=uid
self.name=name
self.status=status
self.level= level
ipython做测试,导入上面的两个类,并实例化
In [4]: from SlotsTest importPlayer1,Player2
In [5]: p1 = Player1('001','cici')
In [6]: p2 = Player2('002','coco')
先说下结论:第一个类比第二个要耗费内存
查看两个类属性的差集,看看第一个类多了什么
In [10]: set(dir(p1))-set(dir(p2))
Out[10]: {'__dict__', '__weakref__'}
!!!重点来了!!!
_dict_方法主要用于动态绑定属性,看下列测试结果
再比较一下两个对象的大小
importsys
In [27]: sys.getsizeof(p1)
Out[27]: 64In [28]: sys.getsizeof(p2)
Out[28]: 80In [29]: sys.getsizeof(p1.__dict__)
Out[29]: 1048
_slots_ = ['uid', 'name', 'status', 'level']
会屏蔽掉对象中的_dict_方法
屏蔽掉之后,对象将无法动态绑定属性
动态绑定函数
我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象:
classPerson(object):def __init__(self, name, score):
self.name=name
self.score=scoredefget_grade(self):return 'A'p1= Person('Bob', 90)printp1.get_grade#=> >
printp1.get_grade()#=> A
也就是说,p1.get_grade 返回的是一个函数对象,但这个函数是一个绑定到实例的函数,p1.get_grade() 才是方法调用。
因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法:
importtypesdeffn_get_grade(self):if self.score >= 80:return 'A'
if self.score >= 60:return 'B'
return 'C'
classPerson(object):def __init__(self, name, score):
self.name=name
self.score=score
p1= Person('Bob', 90)
p1.get_grade=types.MethodType(fn_get_grade, p1, Person)print p1.get_grade()
运行结果: A
p2 = Person('Alice', 65)print p2.get_grade()
运行结果: ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
因为p2实例并没有绑定get_grade
动态构建类
Type函数
第一个参数是类的名字,第二个元组是父类,第三个是属性。
defattr(self):'''定义一个函数,并绑定到对象'''
return 1**2*3.14T= type('TypeClass', (object,), {'a':'Hello', 'attr':attr})
printT.aprint T.__dict__
print T.__name__
运行结果:Hello
dict_proxy({'a': 'Hello', '_module': '_main', 'attr': , '_dict': , '_weakref': , '_doc_': None})
TypeClass
t =T()printt.attr()print t.__dict__
运行结果:3.14
{}
printtype(T)print type(t)
运行结果: