Python中的类作用域与模块作用域属性

2024-04-28 23:45:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我声明了一个类,该类使用定义为类属性的几个硬编码常量进行一些计算。所有方法看起来都类似于以下内容:

class IAPWS_1995:
    @staticmethod
    def dAr_ddelta(delta, tau, Delta, theta, psi):
        _dAr_ddelta = \
            sum(IAPWS_1995.n_0 * IAPWS_1995.d_0 * pow(delta, IAPWS_1995.d_0-1) * pow(tau, IAPWS_1995.t_0)) + \
            sum(IAPWS_1995.n_1 * exp(-pow(delta, IAPWS_1995.c_1)) * (pow(delta, IAPWS_1995.d_1-1) * pow(tau, IAPWS_1995.t_1) * (IAPWS_1995.d_1 - IAPWS_1995.c_1*pow(delta, IAPWS_1995.c_1)))) + \
            sum(IAPWS_1995.n_2 * pow(delta, IAPWS_1995.d_2)*pow(tau, IAPWS_1995.t_2) * exp(-IAPWS_1995.alpha_2*(delta-IAPWS_1995.epsilon_2)**2 - IAPWS_1995.beta_2*(tau-IAPWS_1995.gamma_2)**2) * (IAPWS_1995.d_2/delta - 2*IAPWS_1995.alpha_2*(delta-IAPWS_1995.epsilon_2))) + \
            sum(IAPWS_1995.n_3 * (pow(Delta, IAPWS_1995.b_3)*(psi + delta*IAPWS_1995.dpsi_ddelta(psi, delta)) + IAPWS_1995.dDeltab_ddelta(delta, Delta, theta)*delta*psi))
        return _dAr_ddelta

类范围限定符使代码(甚至更难)难以读取。我曾想过做些类似的事情来提高代码的可读性:

^{pr2}$

但是,如果我将常量声明移到模块范围,我根本不需要范围限定符。在

是否有理由更倾向于在类中声明常量而不是在模块中声明常量(例如,如果将来我有一个类似的类IAPWS_2014,那么名称空间冲突)在


Tags: alpha声明deltasum常量限定符tautheta
2条回答

如果您将来有类似的(可能是现代化的)类,例如IAPWS_2014),那么考虑使用classmethod而不是staticmethod是有意义的:

class IAPWS_1995(object):
  n_3 = 123
  ...  # further class data

  @classmethod
  def dAr_ddelta(c, delta, tau, Delta, theta, psi):
    _dAr_ddelta = \
        sum(c.n_0 * c.d_0 * pow(delta, c.d_0-1) * pow(tau, c.t_0)) + \
        sum(c.n_1 * exp(-pow(delta, c.c_1)) * (pow(delta, c.d_1-1) * pow(tau, c.t_1) * (c.d_1 - c.c_1*pow(delta, c.c_1)))) + \
        sum(c.n_2 * pow(delta, c.d_2)*pow(tau, c.t_2) * exp(-c.alpha_2*(delta-c.epsilon_2)**2 - c.beta_2*(tau-c.gamma_2)**2) * (c.d_2/delta - 2*c.alpha_2*(delta-c.epsilon_2))) + \
        sum(c.n_3 * (pow(Delta, c.b_3)*(psi + delta*c.dpsi_ddelta(psi, delta)) + c.dDeltab_ddelta(delta, Delta, theta)*delta*psi))
    return _dAr_ddelta

这样,这个类的新版本就可以继承旧版本,并且只覆盖实际更改过的变量。如果计算结果发生了变化,则不得重新执行:

^{pr2}$

关于您最初的问题,一个更好的副作用是,您可以随意为类命名参数。cls可能是典型的(根据PEP8,它是canon),但是{}也可以工作,并将代码缩写为您的_版本。在

另一种方法是简单地创建一个名为IAPWS_1995的模块,因为您实际上并没有实例化类中的对象。你的模块看起来像:

n_0, n_1, n_2, n_3 = ...
d_0, d_1, d_2 = ...
t_0, t_1, t_2 = ...
c_1, = ...
b_3, = ...
alpha_2, beta_2, gamma_2, epsilon_2 = ...
dpsi_ddelta = ...
dDeltab_ddelta = ...

def dAr_ddelta(delta, tau, Delta, theta, psi):
    _dAr_ddelta = (
        sum(n_0 * d_0 * pow(delta, d_0-1) * pow(tau, t_0)) +
        sum(n_1 * exp(-pow(delta, c_1)) * (pow(delta, d_1-1) * pow(tau, t_1) * (d_1 - c_1*pow(delta, c_1)))) +
        sum(n_2 * pow(delta, d_2)*pow(tau, t_2) * exp(-alpha_2*(delta-epsilon_2)**2 - beta_2*(tau-gamma_2)**2) * (d_2/delta - 2*alpha_2*(delta-epsilon_2))) + \
        sum(n_3 * (pow(Delta, b_3)*(psi + delta*dpsi_ddelta(psi, delta)) + dDeltab_ddelta(delta, Delta, theta)*delta*psi)))
        return _dAr_ddelta

常量作为模块级变量,类方法是模块级函数。在

其他代码可以这样使用它:

^{pr2}$

相关问题 更多 >