python创建独立副本_python – 在类中创建类的副本

我想在python中对代码进行cython化以加速代码.在下面你可以看到我尝试使我的python类可以理解为cython:

import numpy as np

cimport numpy as np

ctypedef np.double_t DTYPE_T

cpdef double std_G,v_c

std_G=4.3e-9 # Newton's const in Mpc (km/s)^2 M_sol^{-1}

v_c = 299792.458 #km/s

cdef extern from "math.h":

double log(double) nogil

double sqrt(double) nogil

cdef extern from "gsl/gsl_math.h":

ctypedef struct gsl_function:

double (* function) (double x, void * params)

void * params

cdef extern from "gsl/gsl_integration.h":

ctypedef struct gsl_integration_workspace

gsl_integration_workspace * gsl_integration_workspace_alloc(size_t n)

void gsl_integration_workspace_free(gsl_integration_workspace * w)

int gsl_integration_qags(const gsl_function * f, double a, double b, double epsabs, double epsrel, size_t limit, gsl_integration_workspace * workspace, double *result, double *abserr)

cdef double do_callback(double x, void* params):

return (params).eval(x)

cdef class ComovingDistMemoization(object):

cdef list _memotable

cdef cosmolgy

def __cinit__(self, cosmology, memotable = None):

if memotable is None:

self._memotable = []

self._memotable = memotable

self.cosmology = cosmology

def __call__(self, double z):

if z in self._memotable:

return self._memotable[z]

def eval(z):

return 1./sqrt(self.cosmology.hubble2(z))

cdef gsl_integration_workspace* w =gsl_integration_workspace_alloc(1000)

cdef gsl_function F

F.function = &do_callback

F.params = self

cdef double result = 3, error = 5

cdef double y, err, dist

gsl_integration_qags (&F, 0, z, 0, 1e-7, 1000, w, &result, &error)

y, err = result, error

gsl_integration_workspace_free(w)

dist = self.cosmology.v_c * y #to get proper units, ie to put in the hubble length

self._memotable[z] = dist

return dist

cdef class cosmology(object):

cdef comovingdist

cdef public double omega_m, omega_l, h, w, omega_r, G, v_c

cdef double H0, hubble_length

def __init__(self, omega_m = 0.3, omega_l = 0.7, h = 0.7, w = -1, omega_r = 0., G = std_G):

self.omega_m = omega_m

self.omega_l = omega_l

self.omega_r = omega_r

self.h = h

self.w = w

self.G = G

self.v_c = v_c

self.comovingdist = ComovingDistMemoization(self)

def __copy__(self):

return cosmology(omega_m = self.omega_m, omega_l = self.omega_l, h = self.h, w = self.w, omega_r = self.omega_r, G = self.G)

property H0:

def __get__(self):

return 100*self.h #km/s/MPC

def hubble2(self, double z):

cdef double inv_a

inv_a = 1.+z

return (self.omega_r*inv_a**4 + self.omega_m*inv_a**3 + \

self.omega_l*(inv_a**(3*(1+self.w))) + (1 - self.omega_m - self.omega_l - self.omega_r)*inv_a**2)*self.H0**2

property hubble_length:

def __get__(self):

return self.v_c / self.H0

def rho_crit(self, double z):

return 3.*self.hubble2(z)/(8*np.pi*self.G)

def angulardist(self, double z, double z2 = None):

if z2 is None:

return self.comovingdist(z) / (1+z)

return (self.comovingdist(z2) - self.comovingdist(z)) / (1+z2)

然而,其中一个引发错误的地方,到目前为止我找不到任何替换,我的调查刚刚达到这一点,cython不支持__copy __(self)函数.

第一个问题:如何在cython中复制一个类的方法?

我用pickle.Pickler读到了,有可能为类的实例提供替换,但我不知道它应该如何在类中生成类的副本?

更新:

用以下代码替换__copy__是一种正确的方法:

def __reduce__(self):

return (self.__class__, (), self.__getstate__())

def __getstate__(self):

return (self.omega_m, self.omega_l, self.omega_r, self.h, self.w, self.G, self.v_c)

def __setstate__(self, data):

(self.omega_m, self.omega_l, self.omega_r, self.h, self.w, self.G, self.v_c) = data

我的第二个问题是关于属性,我是否在cython中定义了属性,或者我还需要一个__set__函数?

我的最后一个问题:当我使用ComovingDistMemoization调用所有宇宙学类的实例时,它们返回零.我想知道我在ComovingDistMemoization类中调用cosmology类的方式,反之亦然导致问题,并且不能在它们之间传递信息?

解决方法:

回答你的第二个问题,在你的情况下,你不需要__set__函数,似乎你使用__get__概念的方式有误.要获取的属性名称必须设置为:

def get_H0(self):

return 100*self.h #km/s/MPC

H0 = property(fget=get_H0)

def get_hubble_length(self):

return self.v_c / self.H0

hubble_length = property(fget=get_hubble_length)

编辑:我不知道@property不能与Cython一起使用

标签:python,cython,pickle

来源: https://codeday.me/bug/20190703/1364006.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值