在创建实例之前将参数修改为 typing.NamedTuple
Modify arguments to typing.NamedTuple prior to instance creation
我期待着使用有点新的 typing.NamedTuple
class,它允许使用通常的 Python class 创建命名元组 classes ] 语法(包括添加文档字符串和方法、提供默认值、类型提示等的能力)。
但是:底部的 class 产生以下错误消息:
AttributeError: Cannot overwrite NamedTuple attribute __new__
从这里我收集了它所说的内容:覆盖 __new__
仍然是不可以的。这很令人失望。
执行此操作的 "old way" 将继承命名元组 class,但这需要我认为是一些丑陋的样板代码:
from collections import namedtuple
class FormatSpec(namedtuple('FormatSpecBase', 'fill align sign alt zero '
'width comma decimal precision type')):
__slots__ = ()
def __new__(cls, fill, align, sign, alt, zero,
width, comma, decimal, precision, type):
to_int=lambda x: int(x) if x is not None else x
zero=to_int(zero)
width=to_int(width)
precision=to_int(precision)
return super().__new__(cls, fill, align, sign, alt, zero,
width, comma, decimal, precision, type)
FormatSpec.__doc__=_FormatSpec.__doc__.replace('FormatSpecBase','FormatSpec')
在创建命名元组之前,是否有其他替代方法可以将下面的 zero
、width
和 precision
参数转换为 int
,但仍然使用相同的 class 创建语法?还是我坚持使用旧方法?
from typing import NamedTuple, Optional
class FormatSpec(NamedTuple):
"""Represents a string that conforms to the [Format Specification
Mini-Language][1] in the string module.
[1]: https://docs.python.org/3/library/string.html#formatspec
"""
fill: Optional[str]
align: Optional[str]
sign: Optional[str]
alt: Optional[str]
zero: Optional[int]
width: Optional[int]
comma: Optional[str]
decimal: Optional[str]
precision: Optional[int]
type: str
def __new__(cls, fill, align, sign, alt, zero, width, comma, decimal, precision, type):
to_int=lambda x: int(x) if x is not None else x
zero=to_int(zero)
width=to_int(width)
precision=to_int(precision)
return super().__new__(cls, fill, align, sign, alt, zero,
width, comma, decimal, precision, type)
def join(self):
return ''.join('{!s}'.format(s) for s in self if s is not None)
def __format__(self, format_spec):
try:
return format(self.join(), format_spec)
except (TypeError, ValueError):
return super().__format__(format_spec)
一种方法是将其拆分为两个 classes,并在子 class:
中进行参数修改
from typing import NamedTuple, Optional
class FormatSpecBase(NamedTuple):
"""Represents a string that conforms to the [Format Specification
Mini-Language][1] in the string module.
[1]: https://docs.python.org/3/library/string.html#formatspec
"""
fill: Optional[str]
align: Optional[str]
sign: Optional[str]
alt: Optional[str]
zero: Optional[int]
width: Optional[int]
comma: Optional[str]
decimal: Optional[str]
precision: Optional[int]
type: str
def join(self):
return ''.join('{!s}'.format(s) for s in self if s is not None)
def __format__(self, format_spec):
try:
return format(self.join(), format_spec)
except (TypeError, ValueError):
return super().__format__(format_spec)
class FormatSpec(FormatSpecBase):
__slots__ = ()
def __new__(cls, fill, align, sign, alt, zero, width, comma, decimal, precision, type):
to_int=lambda x: int(x) if x is not None else x
zero=to_int(zero)
width=to_int(width)
precision=to_int(precision)
return super().__new__(cls, fill, align, sign, alt, zero,
width, comma, decimal, precision, type)
我不太喜欢这种方法,但至少它比 "old way" 更具可读性(尽管它仍然需要那些悬而未决的 __slots__
废话)。
另一种方式是工厂:
def MakeFormatSpec(cls, fill, align, sign, alt, zero,
width, comma, decimal, precision, type):
to_int=lambda x: int(x) if x is not None else x
zero=to_int(zero)
width=to_int(width)
precision=to_int(precision)
return FormatSpec(fill, align, sign, alt, zero,
width, comma, decimal, precision, type)
fspec = MakeFormatSpec(*parse_format_spec(some_format_spec_string))
...或工厂方法:
@classmethod
def make(cls, fill, align, sign, alt, zero, width, comma, decimal, precision, type):
to_int=lambda x: int(x) if x is not None else x
zero=to_int(zero)
width=to_int(width)
precision=to_int(precision)
return cls(fill, align, sign, alt, zero,
width, comma, decimal, precision, type)
fspec = FormatSpec.make(*parse_format_spec(some_format_spec_string))
然而,与简单地能够做到的相比,这些都非常笨拙:
fspec = FormatSpec(*parse_format_spec(some_format_spec_string))
我期待着使用有点新的 typing.NamedTuple
class,它允许使用通常的 Python class 创建命名元组 classes ] 语法(包括添加文档字符串和方法、提供默认值、类型提示等的能力)。
但是:底部的 class 产生以下错误消息:
AttributeError: Cannot overwrite NamedTuple attribute __new__
从这里我收集了它所说的内容:覆盖 __new__
仍然是不可以的。这很令人失望。
执行此操作的 "old way" 将继承命名元组 class,但这需要我认为是一些丑陋的样板代码:
from collections import namedtuple
class FormatSpec(namedtuple('FormatSpecBase', 'fill align sign alt zero '
'width comma decimal precision type')):
__slots__ = ()
def __new__(cls, fill, align, sign, alt, zero,
width, comma, decimal, precision, type):
to_int=lambda x: int(x) if x is not None else x
zero=to_int(zero)
width=to_int(width)
precision=to_int(precision)
return super().__new__(cls, fill, align, sign, alt, zero,
width, comma, decimal, precision, type)
FormatSpec.__doc__=_FormatSpec.__doc__.replace('FormatSpecBase','FormatSpec')
在创建命名元组之前,是否有其他替代方法可以将下面的 zero
、width
和 precision
参数转换为 int
,但仍然使用相同的 class 创建语法?还是我坚持使用旧方法?
from typing import NamedTuple, Optional
class FormatSpec(NamedTuple):
"""Represents a string that conforms to the [Format Specification
Mini-Language][1] in the string module.
[1]: https://docs.python.org/3/library/string.html#formatspec
"""
fill: Optional[str]
align: Optional[str]
sign: Optional[str]
alt: Optional[str]
zero: Optional[int]
width: Optional[int]
comma: Optional[str]
decimal: Optional[str]
precision: Optional[int]
type: str
def __new__(cls, fill, align, sign, alt, zero, width, comma, decimal, precision, type):
to_int=lambda x: int(x) if x is not None else x
zero=to_int(zero)
width=to_int(width)
precision=to_int(precision)
return super().__new__(cls, fill, align, sign, alt, zero,
width, comma, decimal, precision, type)
def join(self):
return ''.join('{!s}'.format(s) for s in self if s is not None)
def __format__(self, format_spec):
try:
return format(self.join(), format_spec)
except (TypeError, ValueError):
return super().__format__(format_spec)
一种方法是将其拆分为两个 classes,并在子 class:
中进行参数修改from typing import NamedTuple, Optional
class FormatSpecBase(NamedTuple):
"""Represents a string that conforms to the [Format Specification
Mini-Language][1] in the string module.
[1]: https://docs.python.org/3/library/string.html#formatspec
"""
fill: Optional[str]
align: Optional[str]
sign: Optional[str]
alt: Optional[str]
zero: Optional[int]
width: Optional[int]
comma: Optional[str]
decimal: Optional[str]
precision: Optional[int]
type: str
def join(self):
return ''.join('{!s}'.format(s) for s in self if s is not None)
def __format__(self, format_spec):
try:
return format(self.join(), format_spec)
except (TypeError, ValueError):
return super().__format__(format_spec)
class FormatSpec(FormatSpecBase):
__slots__ = ()
def __new__(cls, fill, align, sign, alt, zero, width, comma, decimal, precision, type):
to_int=lambda x: int(x) if x is not None else x
zero=to_int(zero)
width=to_int(width)
precision=to_int(precision)
return super().__new__(cls, fill, align, sign, alt, zero,
width, comma, decimal, precision, type)
我不太喜欢这种方法,但至少它比 "old way" 更具可读性(尽管它仍然需要那些悬而未决的 __slots__
废话)。
另一种方式是工厂:
def MakeFormatSpec(cls, fill, align, sign, alt, zero,
width, comma, decimal, precision, type):
to_int=lambda x: int(x) if x is not None else x
zero=to_int(zero)
width=to_int(width)
precision=to_int(precision)
return FormatSpec(fill, align, sign, alt, zero,
width, comma, decimal, precision, type)
fspec = MakeFormatSpec(*parse_format_spec(some_format_spec_string))
...或工厂方法:
@classmethod
def make(cls, fill, align, sign, alt, zero, width, comma, decimal, precision, type):
to_int=lambda x: int(x) if x is not None else x
zero=to_int(zero)
width=to_int(width)
precision=to_int(precision)
return cls(fill, align, sign, alt, zero,
width, comma, decimal, precision, type)
fspec = FormatSpec.make(*parse_format_spec(some_format_spec_string))
然而,与简单地能够做到的相比,这些都非常笨拙:
fspec = FormatSpec(*parse_format_spec(some_format_spec_string))