Ram*_*nev 9 pycharm python-3.x
我今天刚开始使用PyCharm Community Edition 2016.3.2.每次我从我的函数中分配一个值时at_square,它都会警告我'函数at_square不会返回任何内容',但它肯定会在每个实例中执行,除非在执行期间引发错误,并且函数的每次使用都按预期运行.我想知道为什么PyCharm认为它没有,以及我能做些什么来纠正它.(我知道有一个选项可以禁止该特定函数的警告,但是它通过在函数上方的代码中插入一条注释行来实现,并且我觉得必须记住最后将它取出来也很烦人该项目.)
这是有问题的功能:
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]
Run Code Online (Sandbox Code Playgroud)
如果重要,这更确切地说是一个对象的方法.我坚持使用术语'函数',因为这是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])
Run Code Online (Sandbox Code Playgroud)
PyCharm没有给出任何警告.在at_square,我已经尝试将每一行评论为以下两行:
def at_square(self, square):
file, rank = Board.tup_from_an(square)
return self.board[file][rank]
Run Code Online (Sandbox Code Playgroud)
PyCharm给出了同样的警告.如果我只留下返回线,那么只有那时警告才会消失.PyCharm似乎被同时分配file和rank通过混淆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
Run Code Online (Sandbox Code Playgroud)
更新:在其构造函数中,类Board(所有这些方法的父类)在静态变量中保存对实例的引用instance.self.at_square(square)给出警告,而Board.instance.at_square(square)不是.我仍然会在适当的时候使用前者,但这可以说明PyCharm的想法.
如果返回值静态求值为,则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
Run Code Online (Sandbox Code Playgroud)
在这一点上,Foo.bar是静态推断为(self: Foo) -> None.动态更改quxvia副作用的类型不会更新:
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
Run Code Online (Sandbox Code Playgroud)
问题是您通过动态分配的实例属性覆盖静态推断的类属性.对于静态分析而言,这通常是不可行的.
您可以使用显式类型提示来解决此问题.
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
Run Code Online (Sandbox Code Playgroud)
从Python 3.5开始,您还可以使用内联类型提示.这些对返回类型特别有用.
import typing
class Foo:
def __init__(self):
# initial type hint to enable inference
self.qux: typing.List[int] = [None]
# explicit return type hint to override inference
def bar(self) -> int:
return self.qux[0] # infers return type as int
Run Code Online (Sandbox Code Playgroud)
请注意,依赖推理它仍然是一个好主意!注释只会self.qux使以后更容易更改类型.注释bar主要用于文档和覆盖不正确的推理.
如果需要支持3.5之前的版本,还可以使用存根文件.假设您的班级在foomodule.py,创建一个名为的文件foomodule.pyi.在里面,只需添加带注释的字段和功能签名; 你可以(而且应该)遗漏尸体.
import typing
class Foo:
# type hint for fields
qux: typing.List[int]
# explicit return type hint to override inference
def bar(self) -> int:
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1898 次 |
| 最近记录: |