2017-09-22 15 views
4

다소 새로운 typing.NamedTuple 클래스를 사용하기를 기대했는데, 이는 일반적인 파이썬 클래스 구문을 사용하여 명명 된 튜플 클래스를 생성 할 수있게 해줍니다 (문서 문자열 및 메소드 추가 기능 포함, 기본값, 타입 힌트 등).인스턴스 생성 이전에 typing.NamedTuple에 인수 수정하기

그러나 : 나는 그것이 말하는 단지 무엇을 수집이에서

AttributeError: Cannot overwrite NamedTuple attribute __new__ 

: 하단에있는 클래스는 다음과 같은 오류 메시지가 생성됩니다 __new__을 무시하는 것은 더 노 정지하지 않습니다. 이것은 매우 실망 스럽습니다.

명명 된 튜플 클래스에서 상속하는 것 이것에 대해 갈의 "옛날 방식"하지만 내가 못생긴 상용구 코드로 간주 무엇을 필요

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') 

다른 대체 방법이 있나요 I 명명 된 튜플을 만들기 전에 zero, widthprecision 개의 인수를 int으로 캐스트 할 수 있지만 여전히 동일한 클래스 작성 구문을 사용하고 있습니까? 아니면 옛날 방식으로 붙어 있습니까? 적어도 그것을

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) 

나는이 방법에 대해별로 치료를 할 수 있지만 :

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) 

답변

1

한 가지 방법은 두 개의 클래스로이 분할하고, 자식 클래스의 인수의 수정을하는 것입니다 "구식"보다 더 읽기 쉽습니다 (그래도 여전히 __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))