Python シングルトン モードでは、継承時にサブクラスがシングルトンを直接指すようになり、継承されたクラスのメソッドが無効になります。

class RedisBase:
    __instance = None
    __first_init = None

    def __init__(self, ilog, eilog):
        self._ilog = ilog
        self._eilog = eilog

        if not self.__first_init:
            try:
                # 连接池
                self.client = StrictRedis(
                    host=config.db_config['redis'].get("redis_host"),
                    port=config.db_config['redis'].get("redis_port"),
                    password=config.db_config['redis'].get("redis_pwd"),
                    db=config.db_config['redis'].get("redis_dr_db")
                )
                self.__first_init = True
            except Exception as e:
                if self._eilog:
                    self._eilog.error("[REDIS] error: %s", e, exc_info=e)
                else:
                    print("[REDIS] error: %s" % e)

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = super(RedisBase, cls).__new__(cls)
        return cls.__instance


class SynonymRedis(RedisBase):

    def __init__(self, ilog, eilog):
        super(SynonymRedis, self).__init__(ilog, eilog)

    async def get_synonym_group_id(self, term):
        return await self.client.get("None_syn_{}".format(term))

    async def set_synonym_group_id(self, term, group_id):
        await self.client.set("None_syn_{}".format(term), group_id)

    async def get_synonym_group(self, group_id):
        res = await self.client.smembers("None_syn_group_{}".format(group_id))
        res = decoder(res)
        return res

    async def set_synonym_group(self, group_id, *terms):
        await self.client.sadd("None_syn_group_{}".format(group_id), *terms)

    async def list_synonyms(self):
        for group in self.client.keys("None_syn_group_*"):
            await self.client.smembers(group)

上記は定義した2つの継承関係のクラス、以下はSynonymRedisクラスを使用した操作です

class Synonyms:
    def __init__(self):
        self._dynamic_source = SynonymRedis(info_log, error_log)

    async def get_synonyms(self, term, include_self=True):
        try:
            group_id = await self._dynamic_source.get_synonym_group_id(term)
            terms = await self._dynamic_source.get_synonym_group(group_id)
            if not include_self:
                terms.discard(term)
            return terms
        except Exception as e:
            print(e)

group_id = await self._dynamic_source.get_synonym_group_id(term) を実行すると、エラーが発生します。

AttributeError: 'RedisBase' オブジェクトには属性 'get_synonym_group_id' がありません

ただし、上記のコードは、このメソッドが SynonymRedis クラスに存在することを明確に示しています。

その後、このエラーは、SynonymRedis クラスにメソッドがないことを示すのではなく、RedisBase クラスにこのメソッドがないことを示していることがわかりました。実行すると後で判明しました

self._dynamic_source = SynonymRedis(info_log, error_log)
この文の場合、実際にインスタンス化されるのは SynonymRedis クラスではなく、RedisBase クラスです。

この点について調査した結果、親クラスである RedisBase がシングルトン モードとして定義されており、以前にインスタンス化されていたため、SynonymRedis クラスのインスタンス化が許可されていないことが判明しました。

この問題には、次の 2 つの解決策があります。

1- RedisBase クラスのシングルトン モード制限を削除します。

2- SynonymRedis クラスをグローバルにインスタンス化します。

上記 2 つの方法は、実際のニーズに応じて選択する必要があります。

 

 

おすすめ

転載: blog.csdn.net/u010483897/article/details/103354241