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:
.