赛通的cdef 类 https://cython.readthedocs.io/en/latest/src/tutorial/cdef_classes.html可能就是您想要的:它们比纯 Python 类使用更少的内存,即使在访问成员时会产生更多开销(因为字段存储为 C 值而不是 Python 对象)。
例如:
%%cython
cdef class CTuple:
cdef public unsigned long long int id
cdef public str name
cdef public bint isvalid
def __init__(self, id, name, isvalid):
self.id = id
self.name = name
self.isvalid = isvalid
可以根据需要使用:
ob=CTuple(1,"mmm",3)
ob.id, ob.name, ob.isvalid # prints (2, "mmm", 3)
时间/内存消耗:
首先,我的机器上的基线:
0.258 s 252.4 MB # tuples
0.343 s 417.5 MB # dict
1.181 s 264.0 MB # namedtuple collections
with CTuple
we get:
0.306 s 191.0 MB
其速度几乎一样快,并且需要的内存要少得多。
如果 C 类型的成员在编译时不清楚,可以使用简单的 python 对象:
%%cython
cdef class PTuple:
cdef public object id
cdef public object name
cdef public object isvalid
def __init__(self, id, name, isvalid):
self.id = id
self.name = name
self.isvalid = isvalid
时间安排有点令人惊讶:
0.648 s 249.8 MB
没想到比原来慢这么多CTuple
-version,但至少比命名元组快两倍。
这种方法的一个缺点是它需要编译。然而 Cython 提供cython.inline
它可用于编译动态创建的 Cython 代码。
我已经释放了cynamedtuple https://pypi.org/project/cynamedtuple/可以通过安装pip install cynamedtuple
,并且基于以下原型:
import cython
# for generation of cython code:
tab = " "
def create_members_definition(name_to_ctype):
members = []
for my_name, my_ctype in name_to_ctype.items():
members.append(tab+"cdef public "+my_ctype+" "+my_name)
return members
def create_signature(names):
return tab + "def __init__(self,"+", ".join(names)+"):"
def create_initialization(names):
inits = [tab+tab+"self."+x+" = "+x for x in names]
return inits
def create_cdef_class_code(classname, names):
code_lines = ["cdef class " + classname + ":"]
code_lines.extend(create_members_definition(names))
code_lines.append(create_signature(names.keys()))
code_lines.extend(create_initialization(names.keys()))
return "\n".join(code_lines)+"\n"
# utilize cython.inline to generate and load pyx-module:
def create_cnamedtuple_class(classname, names):
code = create_cdef_class_code(classname, names)
code = code + "GenericClass = " + classname +"\n"
ret = cython.inline(code)
return ret["GenericClass"]
可以如下使用,动态定义CTuple
从上面:
CTuple = create_cnamedtuple_class("CTuple",
{"id":"unsigned long long int",
"name":"str",
"isvalid":"bint"})
ob = CTuple(1,"mmm",3)
...
另一种选择是使用 jit 编译和 Numba 的即时班 https://numba.pydata.org/numba-doc/dev/user/jitclass.html这提供了这种可能性。然而,它们似乎慢得多:
from numba import jitclass, types
spec = [
('id', types.uint64),
('name', types.string),
('isvalid', types.uint8),
]
@jitclass(spec)
class NBTuple(object):
def __init__(self, id, name, isvalid):
self.id = id
self.name = name
self.isvalid = isvalid
结果是:
20.622 s 394.0 MB
所以 numba jitted 课程还不是一个好的选择。