python - `my_instance = MyClass(a, b).my_method(c)` 是可接受的(Pythonic)模式吗?
问题描述
我已经考虑了好几个小时了。我有一个类最终需要(但会在没有的情况下初始化)一些关键属性。此类的子类需要不同的属性。
如果有帮助,这是一个半边数据结构中的顶点、边和面的基本 MeshElement 类。
通常,我需要创建一个与另一个实例相似但不相同的 istance,因此我有如下方法borrow_b
将属性从一个实例复制到另一个实例。
我想不出一个borrow_b
构造函数,a)保留/复制来自 init 的类型提示,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
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,但我喜欢第一个看起来更像构造函数,而且我不相信第一个不是“Pythonic”。
当然,耳朵愿意寻求更好的解决方案。
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)
推荐阅读
- unity3d - unity mobile VR (GoogleVR) 中如何获取头部运动的轴心?
- eclipse - 在安装 TestNG 之前,我的 Eclipse 工作正常。但是在安装 TestNG 之后出现以下异常
- javascript - Cordova PayPal 插件集成 iOS 问题
- angular - 无法设置 null Angular 的属性“src”-Typescript 错误
- java - 在 MapsActivity 中更改 MyLocation 按钮的位置
- android - 使用Delphi10.1在android中以一种形式使用2种不同的样式
- java - Eclipse中用于文本冒险的键绑定
- android - 当emitter.onNext()处于异步循环时如何调用emitter.onComplete()
- c# - 无法在 CookieAuthenticationOptions 中设置 AuthenticationType
- laravel-5 - 如果 Laravel phpunit 测试失败,则打印自定义消息