繁体   English   中英

Python中的类范围与模块范围属性

[英]Class scope vs module scope attributes in 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

类范围限定符使代码(甚至更多)难以阅读。 我曾想过做这样的事情来使代码更具可读性:

...
_ = IAPWS_1995
_dAr_ddelta = \
    sum(_.n_0 * _.d_0 * pow(delta, _.d_0-1) * pow(tau, _.t_0)) + \
...

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

是否有理由更喜欢在模块中声明类中的常量(例如,如果我将来有类似的类IAPWS_2014IAPWS_2014发生命名空间冲突?)

如果您将来有类似的(可能是现代化的)类,例如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

这样,此类的较新版本可以继承旧类,只是覆盖实际已更改的变量。 如果计算没有改变,则不能重新实现:

class IAPWS_2014(IAPWS_1995):
  n_3 = 1234
  ...

关于原始问题的一个更好的副作用是你可以为你喜欢的类命名参数。 cls可能是典型的(并且根据PEP8是正典),但c适用,并且缩写代码与_版本一样。

另一种方法是简单地创建一个名为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

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

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

import IAPW2_1995

x = IAPW2_1995.dAr_ddelta( arg1, arg2, arg3, arg4, arg5 )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM