英文:
In Python, how to specify that a Protocol implementer has a specific constructor signature?
问题
这是您提供的代码的翻译部分:
# Is it possible to define that a class needs a specific constructor?
class Constructible(Protocol):
def __init__(self, i: int): # how do I do this?
raise NotImplementedError
def get_value(self):
raise NotImplementedError
def map_is(cs: Iterable[Constructible], i: int):
mapped = tuple(C(i) for C in cs)
values = tuple(c.get_value() for c in mapped)
# both the constructor and a member method are used
return mapped, values
# implementors (omitting __hash__ and __eq__ for brevity)
class X(Constructible):
def __init__(self, i):
self.i=i
def get_value(self):
return self.i
class Sq(Constructible):
def __init__(self, i):
self.i=i
def get_value(self):
return self.i * self.i
cs, values = tuple(map_is((X, Sq), 5))
assert values == (5, 25)
请注意,上述代码是关于如何在Python中定义一个需要特定构造函数的类以及如何使用该类的示例。如果您有其他问题或需要进一步的信息,请随时提问。
英文:
Is it possible to define that a class needs a specific constructor?
class Constructible(Protocol):
def __init__(self, i: int): # how do I do this?
raise NotImplementedError
def get_value(self):
raise NotImplementedError
def map_is(cs: Iterable[Constructible], i: int):
mapped = tuple(C(i) for C in cs)
values = tuple(c.get_value() for c in mapped)
# both the constructor and a member method are used
return mapped, values
# implementors (omitting __hash__ and __eq__ for brevity)
class X(Constructible):
def __init__(self, i):
self.i=i
def get_value(self):
return self.i
class Sq(Constructible):
def __init__(self, i):
self.i=i
def get_value(self):
return self.i * self.i
cs, values = tuple(map_is((X, Sq), 5))
assert values == (5, 25)
When specifying it like this, I get
$ mypy constr.py
constr.py:12: error: "Constructible" not callable
Found 1 error in 1 file (checked 1 source file)
Is this even possible? Or should I revert to a factory function @classmethod def construct(i: int): Self
?
答案1
得分: 1
如@jonrsharpe所解释的,你不需要将Constructible
实例的可迭代对象传递给map_is
,而是需要传递类的可迭代对象。这意味着你应该这样定义函数:
def map_is(cs: Iterable[Type[Constructible]], i: int):
return (C(i) for C in cs)
这对于mypy来验证代码已足够。
但是有一个无关的问题:你从未声明任何__hash__
或__equal__
特殊方法。这意味着在assert values == (X(5), Sq(5))
中,使用的是object
类上定义的相等性(与is
相同)。因此,在上述修复之后,代码会成功执行,但仍会引发AssertionError
,因为这些对象具有相同的值,但它们是不同的对象...
英文:
As explained by @jonrsharpe, you do not pass an iterable of Constructible
instances to map_is
but an iterable of classes. That means that you should define the function that way:
def map_is(cs: Iterable[Type[Constructible]], i: int):
return (C(i) for C in cs)
That is enough for mypy to validate the code.
But there is an unrelated problem: you never declared any __hash__
nor __equal__
special method. That means that in assert values == (X(5), Sq(5))
the equality used is the one defined on the object
class (same as is
). So after the above fix, the code executes successfully but still raises an AssertionError
, because the objects do have same value, yet they are distinct objects...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论