为什么 Python NewType 不兼容 isinstance 和 type?

问题描述 投票:0回答:5

这似乎不起作用:

from typing import NewType

MyStr = NewType("MyStr", str)
x = MyStr("Hello World")

isinstance(x, MyStr)

我什至没有得到

False
,但是
TypeError: isinstance() arg 2 must be a type or tuple of types
,因为
MyStr
是一个函数,而
isinstance
想要一个或多个
type

即使

assert type(x) == MyStr
is MyStr
也会失败。

我做错了什么?

python
5个回答
0
投票

交叉引用: 从 str 或 int 继承

同一问题更详细:https://stackoverflow.com/a/2673802/1091677


如果您想子类化 Python 的

str
,您需要执行以下操作:

class MyStr(str):
  # Class instances construction in Python follows this two-step call:
  # First __new__, which allocates the immutable structure,
  # Then __init__, to set up the mutable part.
  # Since str in python is immutable, it has no __init__ method.
  # All data for str must be set at __new__ execution, so instead
  # of overriding __init__, we override __new__:
  def __new__(cls, *args, **kwargs):
    return str.__new__(cls, *args, **kwargs)

然后:

x = MyStr("Hello World")

isinstance(x, MyStr)

按预期返回

True


0
投票

与 python 3.10 一样...

我推测答案是 “为什么 Python NewType 与 isinstance 和 type 不兼容?” ...是“这是 NewType 的限制”。

我推测答案是 “我究竟做错了什么?” ... 没什么”。您假设 NewType 创建一个新的运行时类型,但事实似乎并非如此。

不管它的价值如何,我希望它能起作用。


0
投票

也许您想要一个类似于 str 的方法但不是 str 的类型?

获得这种效果的一个简单方法就是:

class MyStr:
    value:str
    def __init__(self,value:str):
       self.value=value
    pass

...但这意味着使用所有字符串方法都是“手动”的,例如

x=MyStr('fred')
x.value.startswith('fr')

...您可以使用@dataclass 添加比较等。

这不是一个一刀切的答案,但它可能适合您的应用。


0
投票

那就简单点吧

class MyStr:
    value:str
    def __init__(self,value:str):
       self.value=value

...像 Str 一样通用(不完整)https://github.com/urnest/urnest/blob/master/xju/newtype.py

...你可以写:

class MyStrType:pass; class MyOtherStrType:pass
class MyStr(Str[MyStrType]):
    pass
class MyOtherStr(Str[MyOtherStrType]):
    pass

x=MyStr('fred')
y=MyOtherStr('fred')
x < y # ! mypy error distinct types MyStr and MyOtherStr

这就是我所追求的,这可能也是你所追求的?我必须单独提供 Int、Str,但根据我的经验,不同的 int、str、float、bool、bytes 类型提供了很多可读性和错误拒绝杠杆。我很快就会将 Float、Bool、Bytes 添加到 xju.newtype 中,并为它们提供所有全套方法。


-1
投票

在 python 3.10 中,外观可能已被“修复”:

https://docs.python.org/3/library/typing.html?highlight=typing#newtype

说:

3.10 版本中的更改:NewType 现在是一个类而不是一个函数。通过常规函数调用 NewType 时会产生一些额外的运行时成本。不过,这个成本将在 3.11.0 中降低。

当我写这篇文章来尝试你的例子时,我手头没有 3.10。

© www.soinside.com 2019 - 2024. All rights reserved.