您可能知道,这是在python中定义命名元组的最新类型:
.react-datepicker__navigation--next {
background: url(../images/rightArrow.png) no-repeat;
width: 15px;
height: 15px;
border: none;
}
定义类型后,Python解释器定义一个获取ID和名称的默认构造函数,您可以使用字段实例化一个新对象。 现在,我想使用一个字符串初始化一个新对象,并在函数中对其进行解析。我该如何定义另一个构造函数而不破坏良好的默认构造函数?
答案 0 :(得分:4)
如何定义另一个构造函数而不破坏良好的默认构造函数?
不能。 Python类不能具有多个__new__
方法(或者,如果您要表示“ initializer”,__init__
方法),则只能是一个。
但是有一个简单的方法可以解决此问题:备用构造函数惯用法:您编写了@classmethod
,它提供了另一种构造实例的方法。标准库中有很多示例,例如datetime.now
和datetime.utcfromtimestamp
。基本内置类型中甚至有一些示例,例如int.from_bytes
。
这是它的工作方式:
class MyType(NamedTuple):
id: int = 0
name: str = 0
@classmethod
def from_string(cls, string_to_parse):
id, name = … your parsing code here …
return cls(id, name)
这当然是您对collections.namedtuple
子类,@dataclass
或具有太多不同构造方法的普通类所做的相同事情。
如果确实要这样做,另一种方法是为丑陋的构造函数提供仅关键字的参数,或者根据传递的内容而具有不同含义的参数。使用NamedTuple
,您将不得不以这种方式插入一个额外的类,或者在创建后对该类进行monkeypatch,因为否则,没有记录的方法可以获取默认的构造函数实现。
所以:
class _MyType(NamedTuple):
id: int = 0
name: str = 0
class MyType(_MyType):
def __new__(cls, id: int=None, name: str=None, *, parseything: str=None):
if parseything:
if id is not None or str is not None:
raise TypeError("don't provide both")
id, name = … your parsing code here …
return super().__new__(cls, id, name)
…,或者,如果您更喜欢猴子补丁:
class MyType(NamedTuple):
id: int = 0
name: str = 0
_new = MyType.__new__
def __new__(cls, id=None, name=None, *, parseything=None):
if parseything:
if id is not None or str is not None:
raise TypeError("don't provide both")
id, name = … your parsing code here …
return _new(cls, id, name)
MyType.__new__ = __new__
del _new
del __new__
…,或者,如果您想要更多的range
风格的丑陋API,则可以使用以下任一方法进行操作:
def __new__(cls, id_or_parsey_thing: Union[int,str]=None,
name: str=None):
if isinstance(id_or_parsey_thing, str):
if name is not None:
raise TypeError("don't provide both")
id, name = … your parsing code here …
else:
id = id_or_parsey_thing
# super().__new__ or _new here
答案 1 :(得分:0)
是的,自Python 3.6起,namedtuple
有一个新的替代方法-NamedTuple。多亏了变量注释,现在才有可能。因此,如果您以前写过类似的内容:
MyType = namedtuple('MyType', ('a', 'b', 'c'))
现在您可以按如下定义它。
要添加新的构造函数,只需定义一个classmethod
:
from typing import NamedTuple
class MyType(NamedTuple):
a: str
b: int
c: float
@classmethod
def from_string(cls, s):
a, b, c = s.split()
return cls(a, int(b), float(c))
print(MyType.from_string('1 2 3'))