我开始为我的程序中应该使用的其中一个类编写草稿,我首先编写了这段代码:
import math
import numpy as np
R = 6.371e6
phi_src, theta_src = 10, 40
phi_det,theta_det = -21, 10
depth_src, depth_det = 0,0 # both on the surface
l = 0
class Trajectory:
def __init__(self,
phi_src,
theta_src,
phi_det,
theta_det,
depth_src,
depth_det,
l):
self.phi_src = phi_src
self.theta_src = theta_src
self.phi_det = phi_det
self.theta_det = theta_det
self.depth_src = depth_src
self.depth_det = depth_det
self.l = l
@property
def r(self):
r_src = R - self.depth_src
r_det = R - self.depth_det
x_src = r_src * math.cos(self.phi_src) * math.cos(self.theta_src)
y_src = r_src * math.cos(self.phi_src) * math.sin(self.theta_src)
z_src = r_src * math.sin(self.phi_src)
x_det = r_det * math.cos(self.phi_det) * math.cos(self.theta_det)
y_det = r_det * math.cos(self.phi_det) * math.sin(self.theta_det)
z_det = r_det * math.sin(self.phi_det)
coord_src = np.array((x_src, y_src, z_src))
coord_det = np.array((x_det, y_det, z_det))
L = np.linalg.norm(coord_src - coord_det)
return math.sqrt(r_src**2 + self.l * (1.0 - L - (r_src - r_det) * (r_src + r_det)/L))
def phi(r):
pass
trajectory = Trajectory(phi_src,theta_src,phi_det,theta_det,depth_src,depth_det,l)
print(trajectory.r)
然后意识到了
r_src = R - self.depth_src
r_det = R - self.depth_det
x_src = r_src * math.cos(self.phi_src) * math.cos(self.theta_src)
y_src = r_src * math.cos(self.phi_src) * math.sin(self.theta_src)
z_src = r_src * math.sin(self.phi_src)
x_det = r_det * math.cos(self.phi_det) * math.cos(self.theta_det)
y_det = r_det * math.cos(self.phi_det) * math.sin(self.theta_det)
z_det = r_det * math.sin(self.phi_det)
coord_src = np.array((x_src, y_src, z_src))
coord_det = np.array((x_det, y_det, z_det))
L = np.linalg.norm(coord_src - coord_det)
部分对于所有类的方法都是通用的,因此在每种方法中无数次计算它都没有意义,这篇文章应该与所有方法共享。
最好的方法是什么?我是否必须将其置于__init__
方法中?我听说在__init__
方法中进行任何计算都不是一个好习惯。
答案 0 :(得分:0)
在不依赖于对象本身状态的类中声明函数的常用方法是使用@staticmethod
装饰器,然后使用函数定义。您只传递函数参数。
如果您需要使用类级别参数,请改用@classmethod
并注意您将cls
而不是self
传递给该函数(可以使用任何变量,所以它确实没有没问题。关键是你现在正在访问类属性和方法而不是对象的属性和方法。
class Trajectory:
c = 10 # <<< Class level property.
def __init__(self):
self.c = 5 # <<< Object level property.
@staticmethod
def foo(a, b):
return a * b
@classmethod
def bar(cls, a, b):
return cls.foo(a, b) * cls.c # <<< References class level method and property.
def baz(self, a, b):
return self.foo(a, b) * self.c # <<< References object level method and property.
t = Trajectory()
>>> t.foo(3, 5)
15
>>> t.bar(3, 5)
150
>>> t.baz(3, 5)
75
答案 1 :(得分:0)
嗯,不完全确定我是否得到了你想要的东西,但引用了你一点......
def r(self):
r_src = R - self.depth_src
r_det = R - self.depth_det
....
L = np.linalg.norm(coord_src - coord_det)
这很常见,你说因为像 def r(self)这样的方法总是其中一些变量,比如 r_src , L :< / p>
def r(self):
return math.sqrt(r_src**2 + self.l * (1.0 - L - (r_src - r_det) * (r_src + r_det)/L))
这个,imho告诉我,如果你想重用那些计算,那么它们应该是__init __(或从__init__调用)的一部分。但大多数情况下,您需要将所有这些变量设置为 self 。
...whereever you compute them in a common location...
self.r_src = R - self.depth_src
self.r_det = R - self.depth_det
....
self.L = np.linalg.norm(coord_src - coord_det)
请注意,由于您依赖于上面的实例变量,例如 self.depth_src ,因此该方法不能是类方法,它必须是实例方法。
现在,将其他方法更改为指向那些预先计算的属性。
def r(self):
return math.sqrt(self.r_src**2 + self.l * (1.0 - self.L ....
现在,您可以通过属性按需计算这些属性。但是如果你问一个相当基本的Python问题,我认为你是这样,那么后来担心优化,现在就做最简单的。即在__init__或从那里调用的方法中计算它们。
现在,有很好的理由将它们从init中分离出来,但它主要与代码清晰度和模块性有关。如果该代码块具有某些特定的数学/业务域含义,则创建一个适当命名的方法并从main调用它。
另一方面,一些IDE和代码分析器在查看__init__中的实例变量时更好地计算实例变量,并且Python是动态的,因为糟糕的东西需要他们可以得到的所有帮助。