«Неразрешенная ссылка на атрибут» в PyCharm - PullRequest
0 голосов
/ 03 ноября 2018

Я получаю предупреждение unresolved attribute reference 'get_opposite_node' for class 'list' в PyCharm, хотя код работает нормально.

Это соответствующая часть кода:

    def bfs(self, start, end):
        visited = {start}  # visited set contains int indices
        start_node = self.Node(start)
        q = deque()
        q.append(start_node)  # deque contains Node objects
        while q:
            cur_node = q.popleft()  # Node object
            if cur_node.idx == end:
                return cur_node 

            for edge in self.get_out_edges(cur_node):
                # HERE IS WHERE I GET THE WARNING:
                child = self.Node(edge.get_opposite_node(i))
                child_idx = child.idx
                if child_idx not in visited:
                    visited.add(child_idx)
                    q.append(child)
                    child.parent = cur_node
        return None

    def get_out_edges(self, node):
        return self.adj[node.idx]

    def add_edge(self, line):
        # line is just a string from the input file 
        (v, u, w) = [int(x) for x in line.split()]
        e = Edge(v,u,w)
        self.adj[v].append(e)
        self.adj[u].append(e)
        self.edges.append(e)

self.adj - список списков: self.adj = [[] for _ in range(N)], который позже заполняется краями класса Edge:

class Edge:
    def __init__(self, v, u, w):
        self.v = v
        self.u = u
        self.w = w

    def get_node(self):
        return self.v

    def get_opposite_node(self, k=None):
        return self.u if k == self.v or k is None else self.v

Итак, в основном, хотя self.adj[i] содержит Edge s, PyCharm считает, что он содержит списки (?). Есть ли способ «убедить» PyCharm, что это не так?

1 Ответ

0 голосов
/ 03 ноября 2018

PyCharm сбит с толку, потому что вы явно объявили adj как list из (пустых) list с. Он не может сказать, что вы впоследствии перезаписали каждый элемент adj объектом, который понимает get_opposite_node(). Но он знает, что вы не можете get_opposite_node() на list.

Вы можете обойти это, объявив adj, чтобы она содержала list из None вместо list пустых list s. Ниже можно уточнить немного:

class RealEdge:
    def get_something(self):
        return "something"


class SomeEdgyThing:
    def __init__(self, size):
        self.adj = [[] for _ in range(size)]


class SomeOtherEdgyThing:
    def __init__(self, size):
        self.adj = [None for _ in range(size)]


class ReallyEdgyThing:
    def __init__(self, size):
        self.adj = [RealEdge() for _ in range(size)]


my_complicated_thing = SomeEdgyThing(7)
for i in range(len(my_complicated_thing.adj)):
    my_complicated_thing.adj[i] = RealEdge()
# PyCharm warning:
#     Unresolved attribute reference 'get_something' for class 'list'
# Runs fine, because we overwrote all the values in adj
# with RealEdges instead of lists.
print(my_complicated_thing.adj[1].get_something())

my_thing = SomeEdgyThing(7)
try:
    # PyCharm warning:
    #     Unresolved attribute reference 'get_something' for class 'list'
    # Also a runtime error:
    #     AttributeError: 'list' object has no attribute 'get_something'
    print(my_thing.adj[1].get_something())
except AttributeError as e:
    print(e)

my_other_thing = SomeOtherEdgyThing(7)
try:
    # PyCharm doesn't complain.
    # Does it assume NoneType is part of a union type...?
    # Runtime error:
    #     AttributeError: 'NoneType' object has no attribute 'get_something'
    print(my_other_thing.adj[1].get_something())
except AttributeError as e:
    print(e)

real_thing = ReallyEdgyThing(7)
# No error
print(real_thing.adj[1].get_something())

Выход:

something
'list' object has no attribute 'get_something'
'NoneType' object has no attribute 'get_something'
something

Я подозреваю, что вам на самом деле не нужно писать self.adj = [[] for _ in range(N)], и что self.adj = [None for _ in range(N)] будет служить так же хорошо и приведет к исчезновению предупреждения.

Теперь вы все еще сталкиваетесь с ситуацией, когда ваш код работает в неправильном порядке, и вы пытаетесь вызвать get_opposite_node() для члена adj, который вы не обновили, чтобы содержать действительное Edge. Тебя просто больше не предупреждают об этом. По этой причине я бы рекомендовал заключить эти вызовы в блок try: ... except AttributeError:.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...