Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多重继承依赖项-基需要AbstractBaseClass_Python_Multiple Inheritance_Abstract Base Class - Fatal编程技术网

Python 多重继承依赖项-基需要AbstractBaseClass

Python 多重继承依赖项-基需要AbstractBaseClass,python,multiple-inheritance,abstract-base-class,Python,Multiple Inheritance,Abstract Base Class,问题的要点是:如果继承多个类,我如何保证如果继承了一个类,子对象也会使用互补抽象基类(abc) 我一直在玩弄pythons继承,试图看看我能做什么样的酷东西,我想出了这个模式,这很有趣 我一直在尝试使用它,使实现和测试与缓存接口的对象变得更容易。我有三个模块: ICachable.py 可缓存的.py 某个班级 ICacheable.py import abc class ICacheable(abc.ABC): @property @abc.abstractmethod

问题的要点是:如果继承多个类,我如何保证如果继承了一个类,子对象也会使用互补抽象基类(abc)

我一直在玩弄pythons继承,试图看看我能做什么样的酷东西,我想出了这个模式,这很有趣

我一直在尝试使用它,使实现和测试与缓存接口的对象变得更容易。我有三个模块:

  • ICachable.py
  • 可缓存的.py
  • 某个班级
ICacheable.py

import abc

class ICacheable(abc.ABC):
    @property 
    @abc.abstractmethod
    def CacheItemIns(self):
        return self.__CacheItemIns
    @CacheItemIns.setter
    @abc.abstractmethod
    def CacheItemIns(self, value):
        self.__CacheItemIns = value
        return
    
    @abc.abstractmethod
    def Load(self):
        """docstring"""
        return

    @abc.abstractmethod
    def _deserializeCacheItem(self): 
        """docstring"""
        return

    @abc.abstractmethod
    def _deserializeNonCacheItem(self): 
        """docstring"""
        return
class Cacheable:
    
    def _getFromCache(self, itemName, cacheType,
                          cachePath=None):
            """docstring"""
    
            kwargs = {"itemName" : itemName, 
                      "cacheType" : cacheType,
                      "cachePath" : cachePath}
    
            lstSearchResult = CacheManager.SearchCache(**kwargs)
            if lstSearchResult[0]:
                self.CacheItemIns = lstSearchResult[1]
                self._deserializeCacheItem()
            else:
                cacheItem = CacheManager.NewItem(**kwargs)
                self.CacheItemIns = cacheItem
                self._deserializeNonCacheItem()
    
            return
可缓存的.py

import abc

class ICacheable(abc.ABC):
    @property 
    @abc.abstractmethod
    def CacheItemIns(self):
        return self.__CacheItemIns
    @CacheItemIns.setter
    @abc.abstractmethod
    def CacheItemIns(self, value):
        self.__CacheItemIns = value
        return
    
    @abc.abstractmethod
    def Load(self):
        """docstring"""
        return

    @abc.abstractmethod
    def _deserializeCacheItem(self): 
        """docstring"""
        return

    @abc.abstractmethod
    def _deserializeNonCacheItem(self): 
        """docstring"""
        return
class Cacheable:
    
    def _getFromCache(self, itemName, cacheType,
                          cachePath=None):
            """docstring"""
    
            kwargs = {"itemName" : itemName, 
                      "cacheType" : cacheType,
                      "cachePath" : cachePath}
    
            lstSearchResult = CacheManager.SearchCache(**kwargs)
            if lstSearchResult[0]:
                self.CacheItemIns = lstSearchResult[1]
                self._deserializeCacheItem()
            else:
                cacheItem = CacheManager.NewItem(**kwargs)
                self.CacheItemIns = cacheItem
                self._deserializeNonCacheItem()
    
            return
某个班级

import ICacheable
import Cacheable

class SomeClass(Cacheable, ICacheable):
    __valueFromCache1:str = ""
    __valueFromCache2:str = ""
    __CacheItemIns:dict = {}
    @property 
    def CacheItemIns(self):
        return self.__CacheItemIns
    @CacheItemIns.setter
    def CacheItemIns(self, value):
        self.__CacheItemIns = value
        return

    def __init__(self, itemName, cacheType):
        #Call Method from Cacheable
        self.__valueFromCache1
        self.__valueFromCache2
        self.__getItemFromCache(itemName, cacheType)
        return

    def _deserializeCacheItem(self): 
        """docstring"""
        self.__valueFromCache1 = self.CacheItemIns["val1"]
        self.__valueFromCache2 = self.CacheItemIns["val2"]
        return

    def _deserializeNonCacheItem(self): 
        """docstring"""
        self.__valueFromCache1 = #some external function
        self.__valueFromCache2 = #some external function
        return

因此,这个例子是可行的,但可怕的是,无法保证继承
Cacheable
的类也继承
ICacheable
。这似乎是一个设计缺陷,因为
可缓存
本身是无用的。然而,用它从我的子类/子类中抽象事物的能力是强大的。有没有办法保证Cacheable对ICacheable的依赖性?

如果您明确不希望继承,可以将类注册为ABC的虚拟子类

@ICacheable.register
class Cacheable:
    ...
这意味着
Cacheable
的每个子类也会自动视为
ICacheable
的子类。如果您有一个高效的实现,而该实现会因为要遍历非功能性抽象基类(例如,对于
super
调用)而减慢速度,那么这将非常有用

然而,ABC不仅仅是接口,从它们继承也不错。事实上,ABC的部分好处在于它强制子类来实现所有抽象方法。中间帮助器类(如
Cacheable
)在从未实例化时不实现所有方法是可以的。但是,实例化的任何非虚拟子类都必须是具体的

>>> class FailClass(Cacheable, ICacheable):
...    ...
...
>>> FailClass()
TypeError: Can't instantiate abstract class FailClass with abstract methods CacheItemIns, Load, _deserializeCacheItem, _deserializeNonCacheItem
请注意,如果

  • 始终将子类设置为
    class AnyClass(可缓存、可缓存):
  • 从不实例化可缓存的
这在功能上相当于从
ICacheable
继承的
Cacheable
。方法分辨率顺序(即继承菱形)相同

>>> AnyClass.__mro__
(__main__. AnyClass, __main__.Cacheable, __main__.ICacheable, abc.ABC, object)

使
Cacheable
成为
ICacheable
@mypetlion的一个子类,让我们进入“如何知道哪些方法需要在Cacheable中重写”的时代。它现在实际上是在实现iCachable,而不是提供帮助实现的Cachable。突然之间,我们又回到了与C#和Java相同的问题上,但是没有一半的继承工具(比如声明类作用域的能力)。至少我是这么想的。为什么要指定私有方法,例如
\u反序列化onCacheItem
,作为接口的一部分?这些内容不应该是可见的,因此您实际上是在实施一个实现细节。还要注意的是,
\uuu CacheItemIns
是一个类私有成员,其名称会被破坏-
ICacheable
不能使用它,除非它声明它。看,对于虚拟子类,这是否意味着Cacheable必须实现ICacheable?这里的部分想法是Cacheable不实现ICacheable。
Cacheable
只需要完全实现
ICacheable
,如果
Cacheable
是一个具体的子类并被实例化。虚拟子类不继承任何内容,包括ABC一致性检查。一个具体但不完整的子类只是一个更专业但仍然是抽象的基类。Cacheable不总是作为构造函数链的一部分被实例化吗?Python中的类型不是这样工作的。如果实例化
SomeClass
,则会实例化并初始化类型为
SomeClass
的对象-其MRO仅包含
可缓存的
。现在,这个实例可以选择像可缓存的
实例一样初始化自己(通过
Cacheable.\uuuuu init\uuuu
super()。\uuuuu init\uuuuu
),但在这期间它仍然是
SomeClass
类型。这意味着它具有满足
ICacheable
所需的所有具体方法。有趣的是,我今天将讨论这个问题。如果我能把这篇文章做好,我会回来给它做正确的标记。谢谢