python - `python`:将返回类实例的类方法放入单独的文件中
问题描述
我有一个大类定义,为了清楚起见,我想在一个单独的文件中分离出算术 dunder 方法。然而,这些方法需要能够返回类的新实例,这会导致循环导入、名称错误或难看的不可维护性。
我想要这样做的动机是最后。
这是一个最小的工作示例。将所有内容放在一个文件中...
#classa.py
class A:
def __init__(self, val):
self.val = val
def __add__(self, other):
return A(self.val + other.val)
...有用:
from .classa import A
a1 = A(30)
a2 = A(21)
(a1 + a2).val # 51
现在,尝试将该__add__
方法放入单独的文件中。
什么不起作用:
尝试 1
#classa.py
from .classa_add import Aarithmatic
class A(Aarithmatic):
def __init__(self, val):
self.val = val
#classa_add.py
from .classa import A
class Aarithmatic:
def __add__(self, other):
return A(self.val + other.val)
在这里,由于循环导入,我们可以理解地得到一个错误:
from .classa import A # <-- ImportError
a1 = A(30)
a2 = A(21)
(a1 + a2).val
尝试 2
以防万一人们指出我这个答案:)
#classa.py
from .classa_add import Aarithmatic
class A(Aarithmatic):
def __init__(self, val):
self.val = val
#classa_add.py
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .classa import A
class Aarithmatic:
def __add__(self, other):
return A(self.val + other.val)
在这里,我们在尝试添加实例时遇到名称错误,这A
是未知的。这是有道理的,这里使用的“解决方案”A
仅用于注释中:
from .classa import A
a1 = A(30)
a2 = A(21)
(a1 + a2).val # <-- NameError: name 'A' is not defined # (in __add__)
尝试 3
我可以这样...
#classa.py
class A:
def __init__(self, val):
self.val = val
#classa_add.py
from .classa import A
def _a_add(self, other):
return A(self.val + other.val)
A.__add__ = _a_add
# Or as oneliner:
A.__add__ = lambda self, other: A(self.val + other.val)
但这首先是非常丑陋和不可读的,其次我必须导入classa_add
只是为了添加添加功能,这令人困惑:
from .classa import A
import .classa_add # <- unclear to reader, why this needs to be here
a1 = A(30)
a2 = A(21)
(a1+a2).val # 51
如果这是一个包,我可以添加一个__init__.py
文件来执行此操作,但它仍然很难看,我相信有更好的解决方案。
有谁知道,更好的解决方案是什么?
非常感谢!
我正在使用python 3.8,顺便说一句。
编辑
推理。为什么我什至想这样做?
我有两个相似的类 (A
和B
),每个类都有很多方法。沿着pandas
DataFrame
和Series
类的思路思考,只是稍微小一点并且不太相似,以至于可以让它们从一个共同的父级继承。目前,每个类都有一个定义它的文件(classa.py
和classb.py
)。
现在,这些文件首先太长,其次,实例上的算术非常相似。
这让我想创建一个单独的文件来定义它的含义a1 + a2
, b1 + b2
, a1 * a2
, b1 * b2
,a + b
以及 and a * b
.
我希望这可以更清楚地说明我为什么要这样做,并且我希望您同意以这种方式拆分类定义更易于维护。
解决方案
您的Aarithmatic
类可以A
通过参数获得调用其方法的时间的引用self
。它根本不需要导入A
。如果在实例__add__
上被调用,那么(或)应该给我们。A
self.__class__
type(self)
A
所以你可以使用:
def __add__(self, other):
return self.__class__(self.val + other.val)
但我也想挑战这个问题的前提,将这些类分开是个好主意(尤其是将它们放在单独的文件中)。如果您发现您正在编写非常紧密集成的代码,那么这些代码都应该放在一起。继承和模块是非常好的工具,但如果你发现它们妨碍了你,这可能表明它们不是解决你当前问题的正确工具。
推荐阅读
- node.js - mocha 是否智能地执行异步代码?
- python - AttributeError:找不到类时,“NoneType”对象没有属性“文本”
- node.js - 类型错误:this.$__setSchema 不是函数
- google-cloud-monitoring - 谷歌云在 python 中获取资源指标响应
- google-bigquery - Bigquery:如何从列中选择多个匹配记录
- calculator - 使用 TI-84 Plus CE 舍入时如何保持尾随零?
- python - raise ValueError(“无效的 DER 输入:数据不足”) ValueError:无效的 DER 输入:数据不足。如何解决此错误
- flutter - 在颤动的页面之间导航的最佳方法是什么
- r - 如何使用 R 中的 ggplot 在一个图中绘制具有多个数据框的列表
- css - 背景视频 CSS