Python数据类中的方法关联

问题描述 投票:0回答:2

我必须维护使用数据类的代码。在这些中,库中的方法被导入并关联,我发现它的完成方式令人困惑并且可读性不太好。它是这样完成的(一个非常简单的例子):

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

这些方法通常对类中包含的数据结构进行操作。

这是常见做法吗?这是执行此操作的正确方法吗?或者应该避免这种情况并以其他方式完成?

python python-dataclasses
2个回答
3
投票

我认为以这种方式定义类方法不是常见的最佳实践。

恕我直言,如果相同的

method_a
method_b
在不同的模块和类中重用,更好的选择是创建一个实现这两种方法的父类,而不是继承它来创建像您显示的那样的新类.

这使得这些方法可以通过不同的输入重用,我猜这些输入是在类的构造函数中定义的变量。

PS:如果没有特殊需要,最好将所有导入放在模块的顶部(正如您的情况所示)。


1
投票

不,这里没有什么是好的做法。让我们一点一点来分解吧

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 程序员。也有可能他们只是很匆忙。
    

© www.soinside.com 2019 - 2024. All rights reserved.