该列表显示了你需要实现你的类方法被"视为"为序列:__getitem__,__len__,__contains__,__iter__,__reversed__,index,和count.那么为什么这个最小的实现不起作用,为什么issubclass(S, Sequence) is False呢?
from collections import *
class S(object):
def __getitem__(self, item):
raise IndexError
def __len__(self):
return 0
def __contains__(self, item):
return False
def __iter__(self):
return iter(())
def __reversed__(self):
return self
def index(self, item):
raise IndexError
def count(self, item):
return 0
issubclass(S, Iterable) # True :-)
issubclass(S, Sized) # True :-)
issubclass(S, Container) # True :-)
issubclass(S, Sequence) # False :-(
Run Code Online (Sandbox Code Playgroud)
我需要实现一个我忽略的额外方法吗?我是否误解了抽象基类?子类化当然 …
python duck-typing subclassing abstract-base-class isinstance
我有一个类似于以下的目录结构:
\n\n.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 model.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 models\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 model_a.py\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 model_b.py\nRun Code Online (Sandbox Code Playgroud)\n\nmodel.py包含一个抽象基类:
from abc import ABCMeta, abstractmethod\n\nclass Base(metaclass=ABCMeta):\n\n @abstractmethod\n def run(self):\n pass\nRun Code Online (Sandbox Code Playgroud)\n\n该models文件夹中有该基类的两个实现,model_a.py和model_b.py,它们将自己注册到主Base类。 model_a.py看起来像这样:
from model import Base\n\nclass ModelA(Base):\n\n def run(self):\n return "a"\n\nModelA.register(Base)\n\nassert issubclass(ModelA, Base)\nRun Code Online (Sandbox Code Playgroud)\n\n并且model_b.py是相似的。
现在,我想做的main.py是创建一个包含所有子类的字典Base,以便我可以选择一个子类(通过程序的 GUI)并运行它:
from model import Base\n\nsubclasses = Base.__subclasses__()\n\ndct = {cls.__name__: cls for cls in subclasses}\n\nklass = dct[\'ModelA\']\nklass.run()\nRun Code Online (Sandbox Code Playgroud)\n\n但我无法让它工作。RuntimeError: …
Python 的PEP 544引入typing.Protocol了结构子类型,也就是“静态鸭子类型”。
在此 PEP 关于合并和扩展协议的部分中,指出
一般的哲学是协议大多像常规的 ABC,但静态类型检查器会专门处理它们。
因此,人们期望从 的子类继承与期望从 的子类继承typing.Protocol的方式大致相同abc.ABC:
from abc import ABC
from typing import Protocol
class AbstractBase(ABC):
def method(self):
print("AbstractBase.method called")
class Concrete1(AbstractBase):
...
c1 = Concrete1()
c1.method() # prints "AbstractBase.method called"
class ProtocolBase(Protocol):
def method(self):
print("ProtocolBase.method called")
class Concrete2(ProtocolBase):
...
c2 = Concrete2()
c2.method() # prints "ProtocolBase.method called"
Run Code Online (Sandbox Code Playgroud)
正如所料,具体子类Concrete1和Concrete2继承method从他们各自的超类。此行为记录在PEP的显式声明实现部分:
要明确声明某个类实现了给定的协议,可以将其用作常规基类。在这种情况下,类可以使用协议成员的默认实现。
...
请注意,显式和隐式子类型之间几乎没有区别,显式子类化的主要好处是“免费”获得一些协议方法。
然而,当协议类实现__init__的方法,__init__是 …
我创建了以下类,以一种以内存效率的方式在平面上存储可变点 - 我需要一个可变的等价物namedtuple('Point', 'x y').由于实例字典很大,我想我会选择__slots__:
from collections import Sequence
class Point(Sequence):
__slots__ = ('x', 'y')
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __getitem__(self, item):
return getattr(self, self.__slots__[item])
def __setitem__(self, item, value):
return setattr(self, self.__slots__[item], value)
def __repr__(self):
return 'Point(x=%r, y=%r)' % (self.x, self.y)
def __len__(self):
return 2
Run Code Online (Sandbox Code Playgroud)
在Python 3上测试时,一切似乎都没问题:
>>> pt = Point(12, 42)
>>> pt[0], pt.y
(12, 42)
>>> pt.x = 5
>>> pt
Point(x=5, y=42)
>>> pt.z = 6
Traceback …Run Code Online (Sandbox Code Playgroud) 我使用的是一个只有纯虚方法的抽象基类,在C++中有一个接口行为(是的,我来自Java).就我的研究而言,这似乎是要走的路.
我必须抽象基类,GraphReader和Graph.
class Graph{
public:
Graph() {};
virtual ~Graph() {};
virtual void layout() = 0;
virtual std::vector<std::shared_ptr<Node>> getNodes() = 0;
virtual std::vector<std::shared_ptr<Edge>> getEdges() = 0;
protected:
};
class GraphReader{
public:
GraphReader(std::string fileName_) :
fileName(fileName_) {};
virtual ~GraphReader() {};
virtual Graph* read() = 0;
protected:
std::string fileName;
};
Run Code Online (Sandbox Code Playgroud)
这两个都有从GraphReader/Graph继承的派生类.
class OgdfGraph : public Graph{
public:
OgdfGraph();
virtual ~OgdfGraph();
void setOgdfGraph(ogdf::Graph &oGraph);
std::vector<std::shared_ptr<Node>> getNodes();
std::vector<std::shared_ptr<Edge>> getEdges();
void layout();
private:
[...]
};
class OgdfGmlReader : public GraphReader {
public:
OgdfGmlReader(std::string fileName);
virtual ~OgdfGmlReader(); …Run Code Online (Sandbox Code Playgroud) 我有一个抽象的基类,它的目的是允许创建一个指向基类的指针数组.(对'很多东西'有用......)
我的抽象基类不包含任何成员函数.因此没有纯虚方法,因此我猜它在技术上并不是抽象的.
但是,我不希望能够创建此类的实例.
是否可以创建无成员抽象基类?如果没有,是否有另一种解决方案来阻止我的"抽象基础"的实例被创建?是否会使构造函数protected足够?
有人向我指出,实际上,如果该类的目的是允许创建指向基类的指针的向量或数组,则不需要抽象基类 - 可能根本就没有基类和使用继承层次结构顶部的类作为基类.或者,可以复制并粘贴该顶级类并交换实现的纯虚函数方法而不实现,但是这在逻辑上与抽象基指针的想法不一致,并且会导致更难以维护代码.
谷歌搜索了一下这一个,但似乎无法找到一个明确的答案.
如何在以下示例中调用unscramble()方法?
谢谢.:^)
class Food {
public:
Food(string _t):type(_t);
virtual void eat() = 0;
private:
string type;
}
class Fruit : public Food {
public:
Fruit(string _t):Food(_t) {
virtual void eat() { // Yummy.. }
}
class Egg : public Food {
public:
Egg(string _t):Food(_t)};
virtual void eat() { // Delicious! };
void unscramble();
}
int main() {
Food *ptr[2];
ptr[0] = new Fruit("Apple");
ptr[1] = new Egg("Brown");
// Now, I want to call the unscramble() method on Egg.
// …Run Code Online (Sandbox Code Playgroud) 我一直在寻找的实施Complex中numbers模块,发现__sub__和__rsub__看起来像这样的实现:
def __sub__(self, other):
""" self - other """
return self + -other
def __rsub__(self, other):
""" other - self """
return -self + other
Run Code Online (Sandbox Code Playgroud)
这困惑了我.
首先,我不确定为什么要实现这些(猜测所有子类都Complex可以回退它?),其次,我无法理解为什么他们选择使用这样的一元-来实现它.
有任何想法吗?
c++ ×3
python ×3
python-3.x ×3
class ×2
c++11 ×1
duck-typing ×1
inheritance ×1
isinstance ×1
numbers ×1
protocols ×1
python-2.x ×1
subclass ×1
subclassing ×1