在python 3中,我可以创建参数并返回类型注释.例:
class Graph:
def __init__(self, V: int, E: int, edges: list):
pass
@classmethod
def fromfile(cls, readobj: type(sys.stdin)):
pass
def V(self) -> int:
pass
def E(self) -> int:
pass
Run Code Online (Sandbox Code Playgroud)
问题是我无法使用当前类(Graph)的返回类型进行注释,该类尚未定义.例:
class Graph:
def reverse(self) -> Graph:
pass
Run Code Online (Sandbox Code Playgroud)
此代码有错误
def reverse(self) -> Graph:
NameError: name 'Graph' is not defined
Run Code Online (Sandbox Code Playgroud)
这些注释对于记录和允许IDE识别参数和返回类型=>启用自动完成非常有用
UPD:所以我提出的是要么是不可能的要么是需要一些我不喜欢的黑客攻击,所以我决定使用def reverse (self) -> 'Graph':
哪种文档是可以理解的,尽管违反了规则.缺点是它不适用于IDE自动完成.
现在Python 3.10已经发布了,在指示参数或返回值可能是可选的(即可以是None. 那么什么是首选:
选项1:
def f(parameter: Optional[int]) -> Optional[str]:
Run Code Online (Sandbox Code Playgroud)
选项2:
def f(parameter: int | None) -> str | None:
Run Code Online (Sandbox Code Playgroud)
Type | None另外,和之间有什么偏好吗None | Type?
以下产生NameError: name 'Client' is not defined.我该如何解决?
class Server():
def register_client(self, client: Client)
pass
class Client():
def __init__(self, server: Server):
server.register_client(self)
Run Code Online (Sandbox Code Playgroud) 我正在创建一个python线性代数模块,用于娱乐和练习语言.我最近尝试向模块添加类型注释,如下所示:
class Vector:
# Various irrelevant implementation details
def __add__(self, other: Vector) -> Vector:
# More implementation details....
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试导入它时,它会吐出一个NameError: Name 'Vector' is not defined.我承认这个问题已经在这里以一种形式得到了回答,但它似乎并没有完全为我的情况提供答案.
我想知道的是什么:
Vector以这样的方式定义它可以用于注释(作为a type)?对于递归函数,我们可以这样做:
def f(i):
if i<0: return
print i
f(i-1)
f(10)
Run Code Online (Sandbox Code Playgroud)
但有没有办法做以下事情?
class A:
# do something
some_func(A)
# ...
Run Code Online (Sandbox Code Playgroud) 我打算使用Python函数注释来指定静态工厂方法的返回值的类型.我知道这是注释的理想用例之一.
class Trie:
@staticmethod
def from_mapping(mapping) -> Trie:
# docstrings and initialization ommitted
trie = Trie()
return trie
Run Code Online (Sandbox Code Playgroud)
PEP 3107指出:
函数注释只不过是一种在编译时将任意Python表达式与函数的各个部分相关联的方法.
Trie是Python中的有效表达式,不是吗?Python不同意或者更确切地说,找不到名称:
def from_mapping(mapping) -> Trie:
NameError: name 'Trie' is not defined
值得注意的是,如果指定了基本类型(例如objector int)或标准库类型(例如collections.deque),则不会发生此错误.
导致此错误的原因是什么?如何解决?
class Node:
def append_child(self, node: Node):
if node != None:
self.first_child = node
self.child_nodes += [node]
Run Code Online (Sandbox Code Playgroud)
我该怎么办node: Node?因为当我运行它时,它说name 'Node' is not defined.
我应该只删除: Node和实例在函数内检查吗?但那我怎么能访问node的属性(我希望它是Node类的实例)?
我不知道如何在Python中实现类型转换,BTW.
以下代码无法按预期工作。显然,我不能在类定义中使用类自己的类型:
class Foo:
def __init__(self, key :str) -> None:
self.key = key
def __eq__(self, other :Foo) -> bool:
return self.key == other.key
print('should be true: ', Foo('abc') == Foo('abc'))
print('should be false: ', Foo('abc') == Foo('def'))
Run Code Online (Sandbox Code Playgroud)
运行结果如下:
Traceback (most recent call last):
File "class_own_type.py", line 1, in <module>
class Foo:
File "class_own_type.py", line 5, in Foo
def __eq__(self, other :Foo) -> bool:
NameError: name 'Foo' is not defined
Run Code Online (Sandbox Code Playgroud)
此外,检查代码mypy返回:
class_own_type.py:5: error: Argument 1 of "__eq__" incompatible with supertype …Run Code Online (Sandbox Code Playgroud) 我在下面包含的代码会引发以下错误:
NameError: name 'Vector2' is not defined
Run Code Online (Sandbox Code Playgroud)
在这一行:
def Translate (self, pos: Vector2):
Run Code Online (Sandbox Code Playgroud)
为什么Python不能Vector2在Translate方法中识别我的类?
class Vector2:
def __init__(self, x: float, y: float):
self.x = x
self.y = y
def Translate(self, pos: Vector2):
self.x += pos.x
self.y += pos.y
Run Code Online (Sandbox Code Playgroud) 我收到错误:
NameError: name 'OrgUnit' is not defined
Run Code Online (Sandbox Code Playgroud)
class OrgUnit(object):
def __init__(self,
an_org_name: str,
its_parent_org_unit: OrgUnit= None
):
self.org_unit_name = an_org_name
self.parent_org_unit = its_parent_org_unit
def __str__(self):
if self.parent_org_unit:
parent_org_unit_name = self.parent_org_unit.__str__()
return parent_org_unit_name + "->" + self.org_unit_name
else:
return self.org_unit_name
if __name__ == '__main__':
ibm_worldwide = OrgUnit("IBM_Worldwide")
ibm_usa = OrgUnit("IBM_USA", ibm_worldwide)
ibm_asia = OrgUnit("IBM_Asia", ibm_worldwide)
ibm_china = OrgUnit("IBM_China", ibm_asia)
print(ibm_worldwide)
print(ibm_usa)
print(ibm_asia)
print(ibm_china)
Run Code Online (Sandbox Code Playgroud)
我确信这是一个已知的范例,因为它似乎是一个非常常见的分层类使用问题(自引用类).我知道我可以改变的类型its_parent_org_unit是object和它的作品,但是这似乎是错误的做法,主要是因为它泄水我检查类型的我的电话的能力.随着its_parent_org_unit改变是一种类型的object我得到正确的结果:
IBM_Worldwide
IBM_Worldwide->IBM_USA
IBM_Worldwide->IBM_Asia
IBM_Worldwide->IBM_Asia->IBM_China
Run Code Online (Sandbox Code Playgroud)
我对这些想法和建议持开放态度.做这种事情最"pythonic"的方法是什么?
PS:这种"自引用类"范例/问题的名称是什么,我可以用来查找其他建议?
python ×10
type-hinting ×7
python-3.x ×4
class ×3
annotations ×2
mypy ×2
oop ×1
python-3.10 ×1
python-3.5 ×1