PyCharm: "функция ничего не возвращает"
я только начал работать с PyCharm Community Edition 2016.3.2 сегодня. Каждый раз, когда я присвоить значение функции at_square
, Он предупреждает меня, что 'функция at_square
ничего не возвращает, но это определенно происходит в каждом случае, если во время выполнения не возникает ошибка, и каждое использование функции ведет себя так, как ожидалось. Я хочу знать, почему Пайчарм думает, что это не так, и могу ли я что-нибудь сделать, чтобы исправить это. (Я знаю, что есть возможность подавить предупреждение для этого конкретная функция, но она делает это, вставляя прокомментированную строку в мой код выше функции, и я нахожу это так же раздражающим, чтобы помнить, чтобы вынуть это в конце проекта.)
это функция, о которой идет речь:
def at_square(self, square):
""" Return the value at the given square """
if type(square) == str:
file, rank = Board.tup_from_an(square)
elif type(square) == tuple:
file, rank = square
else:
raise ValueError("Expected tuple or AN str, got " + str(type(square)))
if not 0 <= file <= 7:
raise ValueError("File out of range: " + str(file))
if not 0 <= rank <= 7:
raise ValueError("Rank out of range: " + str(rank))
return self.board[file][rank]
если это имеет значение, это более точно метод объекта. Я застрял с функцией термин, потому что это язык PyCharm использует.
моя единственная мысль заключается в том, что мое использование ошибки может быть путаешь PyCharm, но это кажется слишком простым. (Пожалуйста, не стесняйтесь критиковать мою ошибку, так как я не уверен, что это идиоматический способ сделать это.)
обновление: С юмором, если я полностью удаляю обратную линию, предупреждение уходит и возвращается немедленно, когда я кладу его обратно. Он также уходит, если я заменяю self.board[file][rank]
С постоянным значением, как 8
. Меняется file
или rank
для постоянных значений не удаляет предупреждение, поэтому я понимаю, что PyCharm как-то запутался в природе self.board
, который представляет собой список из 8 других списков.
обновление: по предложению @StephenRauch я создал минимальный пример, который отражает все, что относится к назначению данных, выполненному at_square
:
class Obj:
def __init__(self):
self.nested_list = [[0],[1]]
@staticmethod
def tup_method(data):
return tuple(data)
def method(self,data):
x,y = Obj.tup_method(data)
return self.nested_list[x][y]
def other_method(self,data):
value = self.method(data)
print(value)
x = Obj()
x.other_method([1,2])
PyCharm не дает никаких предупреждений за это. В at_square
, Я пробовал комментировать каждую строку до двух следующих:
def at_square(self, square):
file, rank = Board.tup_from_an(square)
return self.board[file][rank]
PyCharm дает такое же предупреждение. Если я только уйду ... обратная линия, тогда и только тогда предупреждение исчезает. Кажется, что PyCharm смущен одновременным назначением file
и rank
via tup_from_an
. Вот код для этого метода:
@staticmethod
def tup_from_an(an):
""" Convert a square in algebraic notation into a coordinate tuple """
if an[0] in Board.a_file_dict:
file = Board.a_file_dict[an[0]]
else:
raise ValueError("Invalid an syntax (file out of range a-h): " + str(an))
if not an[1].isnumeric():
raise ValueError("Invalid an syntax (rank out of range 1-8): " + str(an))
elif int(an[1]) - 1 in Board.n_file_dict:
rank = int(an[1]) - 1
else:
raise ValueError("Invalid an syntax (rank out of range 1-8): " + str(an))
return file, rank
обновление: в своем конструкторе класс Board
(который является родительским классом для всех этих методов) сохраняет ссылку на этот экземпляр в статической переменной instance
. self.at_square(square)
дает предупреждение, в то время как Board.instance.at_square(square)
нет. Я все еще собираюсь использовать бывший, когда это уместно, но это может пролить свет на то, что думает PyCharm.
1 ответов
PyCharm принимает отсутствующее возвращаемое значение, если возвращаемое значение статически значение None
. Это может произойти при инициализации значений с помощью None
, и изменение их типа позже.
class Foo:
def __init__(self):
self.qux = [None] # infers type for Foo().qux as List[None]
def bar(self):
return self.qux[0] # infers return type as None
в этот момент Foo.bar
is статически выводится как (self: Foo) -> None
. динамически изменение типа qux
через побочные эффекты не обновляет это:
foo = Foo()
foo.qux = [2] # *dynamic* type of foo.bar() is now ``(self: Foo) -> int``
foo_bar = foo.bar() # Function 'bar' still has same *static* type
проблема в том, что вы переписываете определены статически класс С помощью динамически назначенный экземпляр. Это просто невозможно для статического анализа уловить в целом.
вы можете исправить это с помощью явно намек на тип.
import typing
class Foo:
def __init__(self):
self.qux = [None] # type: typing.List[int]
def bar(self):
return self.qux[0] # infers return type as int