在VASPy中使用延迟初始化
今天重构了VASPy中的OutCar类,使其能够正确操作标准VASP文件,并在其中使用了延迟初始化方法进行了一定的优化。
由于之前版本的VASPy是基于课题组修改过的VASP版本所写的,其中OUTCAR中的一些受力信息是标准VASP代码中不会输出的,但是当时为了省事我就直接拿课题组VASP输出的OUTCAR中的信息写了VASPy中的OutCar
类。。。
为了能让VASPy具有更好的通用性,今天特地重构了OutCar
这个类使其能够操作标准VASP的OUTCAR文件。
具体重构后的OutCar类代码的链接: VASPy/iter.py at master · PytLab/VASPy
由于OUTCAR是VASP所有输出的文件,自然会比较大,因此要操作这个文件就要特别的处理。
使用生成器获取迭代数据
直接读取OUTCAR整个文件必然会占用很多内存,即使不读取整个文件,要把每步迭代的信息都保存的数组中也同样会占用很多的内存。
一个解决的好办法就是使用迭代器来减小内存的开销。而且针对不同数据获取不同的迭代器,比如现在针对OUTCAR中的原子受力数据,我就写了一个force_iterator
函数来获取受力信息的迭代器。
1 |
|
使用延迟初始化(lazy property)
为了给OutCar
实例初始化属性,必须要考虑OUTCAR的大体积,如果在构造实例的时候把所有的属性全部初始化同样会占用大量的内存,为了在内存和CPU进行平衡,我决定使用延迟初始化来处理OutCar
类的属性初始化。
使用延迟初始化一般有两种方法:
使用描述符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23class lazy(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, cls):
val = self.func(instance)
setattr(instance, self.func.__name__, val)
return val
class Circle(object):
def __init__(self, radius):
self.radius = radius
def area(self):
print 'evalute'
return 3.14 * self.radius ** 2
c = Circle(4)
print c.radius
print c.area
print c.area
print c.area使用装饰器,并在装饰器中使用默认的描述符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19def lazy_property(func):
attr_name = "_lazy_" + func.__name__
def _lazy_property(self):
if not hasattr(self, attr_name):
setattr(self, attr_name, func(self))
return getattr(self, attr_name)
return _lazy_property
class Circle(object):
def __init__(self, radius):
self.radius = radius
def area(self):
print 'evalute'
return 3.14 * self.radius ** 2
这里我直接定义了新的描述符来实现延迟初始化,方法很简单,就是定义了一个非描述符(即只有__get__()
方法的描述符)
1 | class LazyProperty(object): |
这样就实现了OutCar
类的延迟初始化。