`my_instance=MyClass(a,b).my_method(c)`是可接受的(Python)模式吗



我已经想了好几个小时了。我有一个类,它最终需要(但不会初始化(一些关键属性。此类的子类需要不同的属性。

如果有帮助的话,这是半边数据结构中的顶点、边和面的基本MeshElement类。

通常,我需要创建一个与另一个实例相似但不相同的istance,所以我有下面的borrow_b这样的方法,可以将属性从一个实例复制到另一个。

我无法想出一个borrow_b构造函数,它a(保留/复制了来自init的类型提示,b(可以由具有不同必需属性的子类继承。

这是我有过的最理智的想法,但它打破了"修改对象的方法返回None"的规则

class AB:
def __init__(self, a: Optional[int] = None, b: Optional[int] = None):
if a is not None:
self.a = a
if b is not None:
self.b = b
def borrow_b(self, other):
self.b = other.b # already type hinted when other was initialized
return self
# >>> one_two = AB(1, 2)
# >>> six_two = AB(6).borrow_b(one_two)

我当然意识到这可以分为两条线:

six_two = AB(6)
six_two.borrow_b(one_two)

并允许borrow_b返回None,但我喜欢第一个看起来更像构造函数,而且我不相信第一个不是"Python">

当然,有更好的解决方案。

FWIW,

six_two = AB(6, six_two.b)

不是一个"可行"的解决方案,因为不是所有我想复制的属性都是"必需的"。我通常想复制一些必需的参数加上通常但不一定附加到网格元素(颜色、紫外线、硬度等(的杂项标记。

使用类方法来实现备用构造函数。对象的目的是跨多个方法调用或函数边界保持状态;创建一个只在一个范围内使用并立即丢弃的对象表明,您首先只需要一个具有适当参数的函数。

class AB:
def __init__(self, a: Optional[int] = None, b: Optional[int] = None):
if a is not None:
self.a = a
if b is not None:
self.b = b
@classmethod
def borrow_b(cls, o1: AB, o2: AB):
return cls(o1.a, o2.b)
one_two = AB(1, 2)
six = AB(6)
six_two = AB.borrow_b(one_two, six)

是的,创建six似乎只是为了初始化six_two,但可能由于其他原因它已经存在了。否则,您可以定义一个类方法,该方法专门接受一个对象和任意一组其他参数来覆盖"原型"。类似的东西

@classmethod
def make_from_prototype(cls, prototype, **kwargs):
new_obj = cls(prototype.a, prototype.b)
for attr, value in kwargs:
setattr(new_obj, attr, value)
return new_obj 
...
one_two = AB(1,2)
six_two = AB.make_from_prototype(one_two, b=6)

一个缺点是make_from_prototype绕过了类型提示,因为**kwargs可以采用任意一组关键字参数。最好用作专用类方法,仅用作borrow_b:等专用类方法的基本实现

@classmethod
def _make_from_prototype(cls, prototype: AB, **kwargs):
# Same definition as above
@classmethod
def borrow_b(cls, o1: AB, o2:AB):
return cls._make_from_prototype(o1, b=o2.b)

相关内容

最新更新