私がコメントしたように、ベースクラスのclassmethodに対してこれを行うのは、定義上、どのメソッドもどのサブクラスとも共有されるため、 に問題があります。これは、特にシングルトンの場合に当てはまります。
回避策は、各サブクラスに適切な戻り値の注釈を持つ同様の名前のメソッドを与えることです。これはクラスのデコレータで行うことができますが、私の答えは、以前のバージョンに示されるように、メタクラスを使用すると、クリーンなアプローチのように思えるので、私はそれに応じて私の答えを更新しました:
class BaseServiceMeta(type):
""" Metaclass that properly annotates the return value of the get_instance() method of
any subclasses of the BaseService class.
"""
def __new__(metaclass, classname, bases, classdict):
cls = super(metaclass, metaclass).__new__(metaclass, classname, bases, classdict)
if classname != 'BaseService': # subclass?
# define function with the correct return value annotation
def get_instance() -> classname:
return super(cls, cls).get_instance() # call superclass classmethod
setattr(cls, 'get_instance', get_instance) # override inherited method
return cls
class BaseService(metaclass=BaseServiceMeta): # metaclass added
instances = {}
@classmethod
def get_instance(cls) -> 'BaseService':
if cls.instances.get(cls) is None:
cls.instances[cls] = cls()
return cls.instances[cls]
class Service1(BaseService):
pass
class Service2(BaseService):
pass
# show that the methods have the correct return annotation
print(repr(BaseService.get_instance.__annotations__['return'])) # -> 'BaseService'
print(repr( Service1.get_instance.__annotations__['return'])) # -> 'Service1'
print(repr( Service2.get_instance.__annotations__['return'])) # -> 'Service2'
# call subclass methods to show they return the correct singleton instance of each type
print(Service1.get_instance()) # -> <__main__.Service1 object at 0x004A07D0>
print(Service2.get_instance()) # -> <__main__.Service2 object at 0x004A07F0>
print(Service1.get_instance()) # -> <__main__.Service1 object at 0x004A07D0>
私はあなたを考えていません'classmethod'のためにこれを行うことができます。なぜなら、クラスクラスのすべての派生クラスとベースクラスによって共有されているからです。単一の正しい戻り値はありません。たとえば、 'Service1.get_instance .__ annotations __ ['return'] = 'Service1'を使ってメソッドの注釈を手動で変更した場合、それはベースクラス内のそのメソッドの' get_instance() 'アノテーションにも影響します。クラス。 – martineau