This doesn't seem to work:
from typing import NewType
MyStr = NewType("MyStr", str)
x = MyStr("Hello World")
isinstance(x, MyStr)
I don't even get False, but TypeError: isinstance() arg 2 must be a type or tuple of types because MyStr is a function and isinstance wants one or more type.
Even assert type(x) == MyStr or is MyStr fails.
What am I doing wrong?
The purpose of NewType is purely for static type checking, but for dynamic purposes it produces the wrapped type. It does not make a new type at all, it returns a callable that the static type checker can see, that's all.
When you do:
x = MyStr("Hello World")
it doesn't produce a new instance of MyStr, it returns "Hello World" entirely unchanged, it's still the original str passed in, even down to identity:
>>> s = ' '.join(["a", "b", "c"]) # Make a new string in a way that foils interning, just to rule out any weirdness from caches
>>> ms = MyStr(s) # "Convert" it to MyStr
>>> type(ms) # It's just a str
str
>>> s is ms # It's even the *exact* same object you passed in
True
The point is, what NewType(...) returns is effectively a callable that:
NewType itself is a class that begins with __call__ = _idfunc, that's literally just saying when you make a call with an instance, return the argument unchanged.| to produce Unions like other typing-friendly things.but you can't use it usefully for isinstance, not because it's not producing instances of anything.
As other answers have mentioned, if you need runtime, dynamic checking, subclassing is the way to go. The other answers are doing both more (unnecessarily implementing __new__) and less (allowing arbitrary attributes, bloating instances of the subclass for a benefit you won't use) than necessary, so here's what you want for something that:
str for both static and runtime checking purposesclass MyStr(str): # Inherit all behaviors of str
__slots__ = () # Prevent subclass from having __dict__ and __weakref__ slots, saving 16 bytes
# per instance on 64 bit CPython builds, and avoiding weirdness like allowing
# instance attributes on a logical str
That's it, just two lines (technically, a one-liner like class MyStr(str): __slots__ = () is syntactically legal, but it's bad style, so I avoid it), and you've got what you need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With