Python TypeHint for Pathlib with Structural Typing (PEP 544)



我有一个项目,其中PosixPath(pathlib(的类型提示将非常有用。我认为这应该是可行的使用这样的结构打字-

# Python 3.8.5
from typing import Protocol
from pathlib import Path, PosixPath
class SupportsPosixPath(Protocol):
def obj(self) -> PosixPath:
...
_home: SupportsPosixPath = Path("~")
_application_dir: SupportsPosixPath = Path("application")
_data_dir: SupportsPosixPath = Path("data")
def do_path_stuff(_home, _application_dir, _data_dir) -> SupportsPosixPath:
_complete_path = _home.joinpath(_application_dir)
_complete_path = _complete_path.joinpath(_data_dir)
_complete_path = _complete_path.expanduser()
_complete_path = (
_complete_path.ascii_lowercase()
)  # This should raise a linter error because PosixPath doesn't support ascii_lowercase.
return _complete_path

PyCharm linter不会引发任何错误/问题。当我对^^^运行mypy时,我得到-

$ mypy foo.py 
foo.py:11: error: Incompatible types in assignment (expression has type "Path", variable has type "SupportsPosixPath")
foo.py:12: error: Incompatible types in assignment (expression has type "Path", variable has type "SupportsPosixPath")
foo.py:13: error: Incompatible types in assignment (expression has type "Path", variable has type "SupportsPosixPath")

如果我将typehint更改为"Path"(如下(,我不会通过mypy或PyCharm linter得到任何错误,但我应该这样做,因为"Path"不支持.ascii_lowercase-

# Python 3.8.5
from typing import Protocol
from pathlib import Path  # , PosixPath

# class SupportsPosixPath(Protocol):
# def obj(self) -> PosixPath:
# ...

_home: Path = Path("~")
_application_dir: Path = Path("application")
_data_dir: Path = Path("data")

def do_path_stuff(_home, _application_dir, _data_dir) -> Path:
_complete_path = _home.joinpath(_application_dir)
_complete_path = _complete_path.joinpath(_data_dir)
_complete_path = _complete_path.expanduser()
_complete_path = (
_complete_path.ascii_lowercase()
)  # This should raise a linter error because PosixPath doesn't support ascii_lowercase.
return _complete_path

在^^^-上运行mypy

$ mypy foo.py 
Success: no issues found in 1 source file

感谢@user2357112_supports_Monica的评论。我不需要创建自己的类型,我需要将类型提示移动到函数中。下面的代码适用于mypi和PyCharm linters-

# Python 3.8.5
from pathlib import Path

_home = Path("~")
_application_dir = Path("application")
_data_dir = Path("data")

def do_path_stuff(_home, _application_dir, _data_dir) -> Path:
_complete_path: Path = _home.joinpath(_application_dir)
_complete_path: Path = _complete_path.joinpath(_data_dir)
_complete_path: Path = _complete_path.expanduser()
return _complete_path

p = do_path_stuff(_home, _application_dir, _data_dir)
print(p)

最新更新