首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >我应该如何在类型批注中表示包含文件路径的字符串的类型?

我应该如何在类型批注中表示包含文件路径的字符串的类型?
EN

Stack Overflow用户
提问于 2019-06-10 11:11:22
回答 1查看 243关注 0票数 1

我正在编写一个库,它提供了一个由最终用户进行子类化的类。类的构造函数关心添加到子类中的方法的参数类型。我希望最终用户能够使用类型注释来指示参数的类型。

我的类关心的一件事是参数是否是包含文件路径的字符串。从逻辑上讲,这应该是str的一个子类型,可以这样表示:

代码语言:javascript
复制
import mylib
from typing import *

FilePath = NewType('FilePath', AnyStr)

class MySubclass(mylib.MyClass):
    def my_method(self, path: FilePath):
        return open(path)

但是typing.NewType的文档字符串给出了以下示例:

代码语言:javascript
复制
from typing import *

UserId = NewType('UserId', int)

def name_by_id(user_id: UserId) -> str:
    ...

name_by_id(42)          # Fails type check
name_by_id(UserId(42))  # OK

因此,为了让静态类型检查器不会导致使用我的库的代码失败,用户必须执行以下操作:

代码语言:javascript
复制
from mylib import *

... # MySubclass defined as above

o = MySubclass()
o.my_method(FilePath('foo/bar.baz'))

但我希望他们能够简单地

代码语言:javascript
复制
o.my_method('foo/bar.baz')

没有静态类型检查器抛出错误。这更多的是因为我担心我正在定义的类型的语义,而不是因为任何人实际使用我的代码并费心在它上运行静态类型检查器的危险。

一种解决方案是将FilePath定义为

代码语言:javascript
复制
FilePath = Union[AnyStr, NewType('FilePath', AnyStr)]

但这看起来很混乱,它的__repr__是一个直截了当的谎言:

代码语言:javascript
复制
>>> FilePath
Union[Anystr, FilePath]

有没有更好的方法?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-11 02:58:13

您的两个目标是不兼容的:您不能同时指定您的方法只接受一个特定的类似路径的对象(甚至是str的一个特定子类型),同时允许调用者直接传入一些任意的str。

你需要从这两个中选择一个。

如果您决定使用前一种方法(指定该方法只接受特定的类似路径的对象),那么使用NewTypes的另一种更令人满意的替代方法可能是改为让您的方法只接受pathlib.Path objects

代码语言:javascript
复制
from pathlib import Path

class MyClass:
    def my_method(self, x: Path) -> None: ...

MyClass().my_method(Path("foo/bar.baz"))

您的调用者仍然需要将其字符串转换为这些Path对象,但至少现在他们将从这样做中获得一些实际的运行时好处。

如果您决定使用后一种方法(允许用户直接传入字符串),那么您不妨去掉所有的str (或者Union[Text, bytes]AnyStr),直接使用str。这将是一个更诚实的类型签名:

代码语言:javascript
复制
class MyClass:
    def my_method(self, x: str) -> None: ...

MyClass().my_method("foo/bar.baz")

您也许可以通过使用类型别名使其更具可读性,如下所示:

代码语言:javascript
复制
MaybeAPath = str

class MyClass:
    def my_method(self, x: MaybeAPath) -> None: ...

MyClass().my_method("foo/bar.baz")

...but这只是一个可读性的改进。为了实现完全的类型安全,如果你的代码和子类的代码接收到一些不能被解析为路径的随机字符串,那么它们仍然需要包含一些错误处理。

我个人倾向于在任何地方都使用pathlib.Path对象,这是有价值的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56520059

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档