我正在尝试编写一个名为
Singleton
的元类,当然,它实现了单例设计模式:
class Singleton(type):
def __new__(cls, name, bases = None, attrs = None):
if bases is None:
bases = ()
if attrs is None:
attrs = {}
new_class = type.__new__(cls, name, bases, attrs)
new_class._instance = None
return new_class
def __call__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = cls.__new__(cls, *args, **kwargs)
cls.__init__(cls._instance, *args, **kwargs)
return cls._instance
这似乎工作正常:
class Foo(metaclass = Singleton):
pass
foo1 = Foo()
foo2 = Foo()
print(foo1 is foo2) # True
但是,PyCharm 给了我这个警告
cls._instance = cls.__new__(cls, *args, **kwargs)
:
Expected type 'Type[Singleton]', got 'Singleton' instead
...这是
cls.__init__(cls._instance, *args, **kwargs)
:
Expected type 'str', got 'Singleton' instead
我在同一个文件上运行 mypy,它是这样说的:
# mypy test.py
Success: no issues found in 1 source file
我使用的是 Python 3.11、PyCharm 2023.1.1 和 mypy 1.3.0,如果有区别的话。
那么这里到底有什么问题呢?我这样做正确吗?这是 PyCharm、mypy 或其他东西的错误吗?如果错误在我身上,我该如何解决?
既然你也在问“我这样做对吗?”,你为什么不使用这样一个更简单的解决方案:
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class Foo(metaclass=SingletonMeta):
...
foo1 = Foo()
foo2 = Foo()
print(foo1 is foo2) # still True
这样可以避免构造造成混淆和警告。我很感激我没有回答为什么 PyCharm 正在检测您认为不正确的类型冲突的问题——它们可能是,我没有深入挖掘以弄清楚为什么 PyCharm 会这么想。
如果你只是想摆脱警告,在你确定问题没有被正确识别之后:
# noinspection PyTypeChecker
cls._instance = cls.__new__(cls, *args, **kwargs)
如果您发现到底出了什么问题,您应该向 JetBrains 提交错误报告(并在您的#noinspection 中添加一个#todo 以提醒您自己在修复后将其删除)。