작성
·
252
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
타입체커가 코드를 분석해가면서 타입들이 바르게 연결 되었는지 검사하는데,
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이 아님을 명시