• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    미해결

문수미님과 같은 내용입니다

22.06.07 08:02 작성 조회수 189

1

코드를 살펴봐도 원인을 모르겠어서 질문 드립니다

 

mypy와 pyright 사용시에 각각 다르게 에러가 나고 내용은 아래와 같습니다

 

mypy

error: Item "None" of "Optional[Node[Any]]" has no attribute "item"

 

pyright

error: "pointer" is not a known member of "None"

.

.

error: "item" is not a known member of "None"

 

아마 Optional[Node]에서 None으로 처리될 때 pointer와 item속성이 없어서 이렇게 되는 것 같은데, 처리 방법을 찾지 못해서 질문 남깁니다.

 

아래는 전체 코드와 에러발생 위치입니다.

 

from typing import Optional, Generic, TypeVar

T = TypeVar("T")

class Node(Generic[T]):
    def __init__(self, item: T, pointer: Optional['Node'] = None):
        self.item = item
        self.pointer = pointer


class LinkedList(Generic[T]):
    def __init__(self):
        self.head: Optional[Node[T]] = None

    @property
    def length(self) -> int:
        if self.head is None:
            return 0
        cur_node = self.head
        count: int = 1
        while cur_node.pointer is not None:
            cur_node = cur_node.pointer
            count += 1
        return count


class Stack(Generic[T], LinkedList[T]):
    def push(self, item: T) -> None:
        new_node: Node[T] = Node[T](item)
        if self.head is None:
            self.head = new_node
            return
        cur_node = self.head
        while cur_node.pointer is not None:
            cur_node = cur_node.pointer
        cur_node.pointer = new_node

    
    def __str__(self) -> str:
        result: str = ''
        if self.head is None:
            return result
        cur_node: Node[T] = self.head
        result += f"{cur_node.item}"
        while cur_node.pointer is not None:
            cur_node = cur_node.pointer
            result += f", {cur_node.item}"
        return result
    
        
    def pop(self) -> T:
        if self.head is None:
            raise ValueError("Stack is Empty")
        cur_node = self.head
        if cur_node.pointer is None:
            self.head = None
            return cur_node.item
        while cur_node.pointer.pointer is not None:                  # <- pyright error "pointer" is not... x2
            cur_node = cur_node.pointer                  # <- pyright error "pointer" is not...
        result = cur_node.pointer                  # <- pyright error "pointer" is not...
        cur_node.pointer = None                  # <- pyright error "pointer" is not...
        return result.item                  # <- mypy error / pyright error "item" is not ...
    

if __name__ == '__main__':
    stack = Stack[int]()
    stack.push(0)
    stack.push(1)
    stack.push(2)
    stack.push(3)
    stack.push(4)
    stack.push(5)
    stack.push(6)
    stack.push(7)
    stack.push(8)
    stack.push(9)
    
    print(stack.length)
    print(stack)
    
    print(stack.pop())
    print(stack.pop())
    print(stack.pop())
    print(stack.pop())
    print(stack.pop())
    print(stack.pop())
    print(stack.pop())
    print(stack.pop())
    print(stack.pop())
    print(stack.pop())

답변 1

답변을 작성해보세요.

2

cloud_dev님의 프로필

cloud_dev

2022.08.15

타입체커가 코드를 분석해가면서 타입들이 바르게 연결 되었는지 검사하는데, 

1. pyright 의 경우,

while cur_node.pointer.pointer is not None:
    cur_node = cur_node.pointer  

에서 cur_node를 cur_node. pointer 로 찍을때  point 가 None이 아닌지 명시되지 않아서 에러가 나는 걸로 보이구요.

2. mypy의 경우 result = cur_node.pointer 로 할당 하면, pointer가 None인지 아닌지 mypy에서 알지 못해서 에러가 나는 걸로 보입니다.

3. 아래와 같이 작성하시면 코드가 좀 더 장황해지기는 하나 mypy, pyright 둘다 통과 합니다. mypy 랑 pyright랑 검사하는 방식이나 유추하는 문맥이 좀 다르긴 하네요.

    def pop(self) -> Optional[T]:
        if self.head is None:
            raise ValueError("Stack is empty")
        cur_node: Node[T] = self.head
        if cur_node.pointer is None:
            self.head = None
            return cur_node.item
        while cur_node.pointer is not None: # cur_node.pointer가 None 이 아님을 명시
            if cur_node.pointer.pointer is not None: 
                cur_node = cur_node.pointer
                continue
            result = cur_node.pointer
            cur_node.pointer = None
            return result.item if result is not None else None # result가 None이 아님을 명시