我必须维护使用数据类的代码。在这些中,库中的方法被导入并关联,我发现它的完成方式令人困惑并且可读性不太好。它是这样完成的(一个非常简单的例子):
from dataclasses import dataclass
from code.custom.package import method_a, method_b
@dataclass
class myClass:
import numpy as np
var1: str
var2: str
var3: np.ndarray = None
myClass.method_a = method_a
myClass.method_b = method_b
这些方法通常对类中包含的数据结构进行操作。
这是常见做法吗?这是执行此操作的正确方法吗?或者应该避免这种情况并以其他方式完成?
我认为以这种方式定义类方法不是常见的最佳实践。
恕我直言,如果相同的
method_a
和 method_b
在不同的模块和类中重用,更好的选择是创建一个实现这两种方法的父类,而不是继承它来创建像您显示的那样的新类.
这使得这些方法可以通过不同的输入重用,我猜这些输入是在类的构造函数中定义的变量。
PS:如果没有特殊需要,最好将所有导入放在模块的顶部(正如您的情况所示)。
不,这里没有什么是好的做法。让我们一点一点来分解吧
from dataclasses import dataclass
from code.custom.package import method_a, method_b
这很好。
dataclasses
既现代又实用。有些人更喜欢将每个导入的符号放在自己的行上,例如
from dataclasses import dataclass
from code.custom.package import method_a
from code.custom.package import method_b
但我不会称其为普遍做法。
@dataclass
class myClass:
我们有一个
dataclass
。这意味着我们免费获得 __eq__
、一个很好的构造函数和一个很好的字符串表示形式。从基本上所有标准来看,类名都很奇怪。通常,我们用 StudlyCaps
来命名类,并且 Python 中没有使用 camelCase
约定的名称(除了像 logging
这样非常旧的标准库模块)。所以这立刻让我觉得很奇怪。
import numpy as np
对于进口来说,这是一个极其奇怪的地方。导入几乎总是位于文件的顶部。有时,您会在针对特定配置功能的顶级
if
语句中看到它们(例如,可能仅在 Windows 上需要的支持库)。有时,您会在函数的开头看到仅在该函数中需要的功能的导入(尽管我通常会尽量避免这种情况)。把它放在课堂上真是奇怪。它总是会被无条件地评估,所以它绝对应该位于文件的顶部。
var1: str
var2: str
好吧,这里没什么可看的。两个必需的
str
类型变量。我觉得很好。
var3: np.ndarray = None
这将使任何有信誉的类型检查器都失败。我们声明该变量的类型为
np.ndarray
,但为其分配了值
None
,这显然不是Numpy 数组。 如果
None
是该字段的有效值,我们应该写
var3: np.ndarray | None = None
或 var3: Optional[np.ndarray] = None
。或者,如果我们只是不关心类型检查,我们应该编写 var3: Any = None
(Optional
和 Any
来自 typing
模块)。
myClass.method_a = method_a
myClass.method_b = method_b
现在是你问题的要点。这也是非常奇怪的事情。我唯一一次看到真正的 Python 代码像这样在类之外分配字段是如果该字段属于类类型。所以类似
class MyClass:
...
MyClass.SINGLETON = MyClass(...)
类需要完全存在并定义才能定义字段。以这种方式分配方法实在是太奇怪了。如果你写的话就不会那么奇怪了
class MyClass:
method_a = imported_method_a
method_b = imported_method_b
老实说,我认为
大多数Python类型检查器都会接受这一点,因为函数对象是完全有效的描述符。我仍然不会选择这样写,但这样会不那么奇怪。正如 mattiatantardini 的回答中提到的,这些通用方法可能应该位于某个超类中,可能是一个“抽象类”,但也可能只是一个 mixin。然后你可以继承你自己的类(数据类在继承方面表现得很好,特别是与它们的原始前身,namedtuples相比)。 所以,总而言之,不,这段代码不是传统的Python,很抱歉您不得不维护它而感到不高兴。如果您的文化允许,您可能可以对此代码进行很多改进。 我能想到的唯一可以在类之外分配方法的地方是非常非常古老的 Javascript。如果您在十五年前编写 Javascript(在 JS 中存在
class
之前),那么您将定义一个构造函数
MyClass
,然后在构造函数外部为
MyClass.prototype
分配方法。编写这段代码的人有可能是 2010 年的 Javascript 程序员。也有可能他们只是很匆忙。