Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
my_instance=MyClass(a,b)。my_方法(c)`是一种可接受的(Pythonic)模式吗?_Python_Python 3.x_Conventions - Fatal编程技术网

my_instance=MyClass(a,b)。my_方法(c)`是一种可接受的(Pythonic)模式吗?

my_instance=MyClass(a,b)。my_方法(c)`是一种可接受的(Pythonic)模式吗?,python,python-3.x,conventions,Python,Python 3.x,Conventions,我已经想了好几个小时了。我有一个类,它最终需要(但不需要)一些关键属性。此类的子类需要不同的属性 如果有帮助,这是半边数据结构中顶点、边和面的基本MeshElement类 通常,我需要创建一个与另一个实例相似但不完全相同的距离,因此我有如下方法将属性从一个实例复制到另一个实例 我无法想出一个borrow\b构造函数,该构造函数a)保留/复制了init中的类型暗示,b)可以由具有不同必需属性的子类继承 这是我有过的最明智的想法,但它打破了“修改对象的方法不返回任何对象”的规则 我当然意识到这可以分

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

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

通常,我需要创建一个与另一个实例相似但不完全相同的距离,因此我有如下方法将属性从一个实例复制到另一个实例

我无法想出一个
borrow\b
构造函数,该构造函数a)保留/复制了init中的类型暗示,b)可以由具有不同必需属性的子类继承

这是我有过的最明智的想法,但它打破了“修改对象的方法不返回任何对象”的规则

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

six_two = AB(6)
six_two.borrow_b(one_two)
。。。并允许
borrow\u b
返回None,但我喜欢第一个看起来更像一个构造函数,我不相信第一个不是“Pythonic”

当然,大家都在等待更好的解决方案

FWIW


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

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

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\u 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\u from\u 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)

我很难理解这里的问题,但我的第一反应是:构造函数只是另一种可调用的。如果您的调用站点不清晰,那么要求在callable中使用关键字参数通常是一种使其更清晰的好方法。更实际的做法是:从您希望调用站点的外观开始,然后向后看代码需要如何工作才能实现这一点。不幸的是,kwargs的settattr(据我所知)能够绕过类型暗示。只要a和b在init中是显式参数就可以了,但是子类可能有不同的显式参数;我会尽力解决这个问题。谢谢你看。在类方法中初始化o1的问题是,我必须在该类方法的某个地方解释我的“必需”参数。o1.someattr被识别为非任意kwarg(并因此被提示为类型)的唯一方法是通过init(或init的近副本)。如果我不想用不同的init子类AB,这是可以接受的。怎么会呢
o1
o2
必须是
AB
的实例,要创建的参数在
中键入。在
borrow\u b
内部,
o1.a
o2.b
必须具有正确的类型,因为它们来自由
初始化的对象。(假设您总是使用
\uuuu init\uuuu
来初始化它们,而不是在创建实例后手动设置属性值。)没错,我可以使用classmethod合并两个现有实例,我甚至可以执行类似于我的实例=ABconstructor(AB(a=6),one\u-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)
@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)