我正在尝试子类化type以创建一个允许构建专用类型的类.例如ListType:
>>> ListOfInt = ListType(list, value_type=int)
>>> issubclass(ListOfInt, list)
True
>>> issubclass(list, ListOfInt)
False
>>> # And so on ...
Run Code Online (Sandbox Code Playgroud)
但是,这ListOfInt永远不会用于创建实例!我只是将它用作type我可以操作以与其他类型进行比较的实例...特别是在我的情况下,我需要查找合适的操作,根据输入的类型,我需要的类型为包含更多精度(如list of int或XML string等).
所以这就是我提出的:
class SpzType(type):
__metaclass__ = abc.ABCMeta
@classmethod
def __subclasshook__(cls, C):
return NotImplemented
def __new__(cls, base, **features):
name = 'SpzOf%s' % base.__name__
bases = (base,)
attrs = {}
return super(SpzType, cls).__new__(cls, name, bases, attrs)
def __init__(self, base, **features):
for name, value in features.items():
setattr(self, name, …Run Code Online (Sandbox Code Playgroud) 扩展抽象基类和从"对象"派生的类可以正常工作:如果您尚未实现所有抽象方法和属性,则会出现错误.
奇怪的是,用扩展"Exception"的类替换对象派生类允许您创建不实现所有必需的抽象方法和属性的类的实例.
例如:
import abc
# The superclasses
class myABC( object ):
__metaclass__ = abc.ABCMeta
@abc.abstractproperty
def foo(self):
pass
class myCustomException( Exception ):
pass
class myObjectDerivedClass( object ):
pass
# Mix them in different ways
class myConcreteClass_1(myCustomException, myABC):
pass
class myConcreteClass_2(myObjectDerivedClass, myABC):
pass
# Get surprising results
if __name__=='__main__':
a = myConcreteClass_1()
print "First instantiation done. We shouldn't get this far, but we do."
b = myConcreteClass_2()
print "Second instantiation done. We never reach here, which is good."
Run Code Online (Sandbox Code Playgroud)
... ...产量 …
以下两个属性定义在Sphinx autodoc html输出中显示完全相同:
@property
def concrete(self):
"""This is the concrete docstring"""
pass
@abstractproperty
def abstract(self):
"""This is the abstract docstring"""
pass
Run Code Online (Sandbox Code Playgroud)
Sphinx是否有办法用某种标识符注释抽象方法?我希望在我的文档中可以明显看出我的ABC成员需要实现哪些,以及一旦定义了所需的,就会获得mixin免费赠品.
如何找到给定类是"虚拟子类"的所有抽象基类?
换句话说,我正在寻找一个virtual_base_classes()像这样的魔术函数:
>>> for cls in virtual_base_classes(list):
>>> print(cls)
<class 'collections.abc.MutableSequence'>
<class 'collections.abc.Sequence'>
<class 'collections.abc.Sized'>
<class 'collections.abc.Iterable'>
<class 'collections.abc.Container'>
Run Code Online (Sandbox Code Playgroud)
(我不知道所有注册的abc类list,所以上面的例子可能不完整.)
请注意,并非每个抽象基类都将被定义collections.abc.有一个模块abc(不同于collections.abc)提供了元类ABCMeta.任何类都是ABCMeta使用标准接口(register方法)支持"虚拟子类"注册的实例.没有什么可以阻止某人(程序员或Python库)创建一个ABCMeta不属于的实例collections.abc.
我用 abc 包实现了抽象类。下面的程序显示没有问题。
有没有办法让它失败,因为抽象MyMethod确实有一个参数,a但类中的“MyMethod”的实现Derivative没有?所以我不仅要指定接口类中的方法,还要指定Base这些方法的参数。
import abc
#Abstract class
class Base(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def MyMethod(self, a):
'MyMethod prints a'
class Derivative(Base)
def MyMethod(self):
print 'MyMethod'
Run Code Online (Sandbox Code Playgroud) 我有一个抽象基类:
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class A(object):
@abc.abstractmethod
def f(self, arg1):
pass
Run Code Online (Sandbox Code Playgroud)
我想使用此类作为模拟的规范。
import mock
mock_a = mock.Mock(spec=A)
Run Code Online (Sandbox Code Playgroud)
这部分起作用。例如,mock_a.x结果为AttribureError("Mock object has no attribute 'x')。但是mock_a.f,并未基于的抽象方法进行说明A.f。无论传递给的参数数量如何,它都会返回一个模拟f。
mock_a = mock.Mock(spec=A)
# Succeeds
print mock_a.f(1)
# Should fail, but returns a mock
print mock_a.f(1,2)
# Correctly fails
print mock_a.x
Run Code Online (Sandbox Code Playgroud)
模拟可以创建speced一个模拟A.f带create_autospec...
f_spec = mock.create_autospec(A.f)
# Succeeds
f_spec(mock_a, 1)
# Correctly fails
f_spec(mock_a, 1, 2)
Run Code Online (Sandbox Code Playgroud)
...但是对于A的属性却不这样做
如何创建可以准确实现抽象基类的模拟?
我有这样的功能
def print_stuff(items):
if isinstance(items, (str, bytes)):
items = (items,)
for item in items:
print (item)
Run Code Online (Sandbox Code Playgroud)
可以这样称呼:
In [37]: print_stuff(('a', 'b'))
a
b
In [38]: print_stuff('a')
a
Run Code Online (Sandbox Code Playgroud)
我不喜欢做,isinstance (items, (str, bytes))我更愿意做isinstance(item, (collections.abc.MAGIC))
其中MAGIC是所有序列对象的ABC,可以包含其他序列对象,例如
但不是:
恐怕这是不可能的,tuple并且str具有相同的7个ABC :(
In [49]: [v for k, v in vars(collections.abc).items()
...: if inspect.isclass(v) and issubclass(tuple, v) ]
Out[49]:
[collections.abc.Hashable,
collections.abc.Iterable,
collections.abc.Reversible,
collections.abc.Sized,
collections.abc.Container,
collections.abc.Collection,
collections.abc.Sequence]
In [50]: [v for k, v in …Run Code Online (Sandbox Code Playgroud) 我的问题如下:我想创建一个继承自typing.NamedTuple的类和另一个抽象类中的mixin。理想情况下我想做这样的事情:
from typing import *
from abc import ABC, abstractmethod
class M(ABC):
@abstractmethod
def m(self, it: Iterable[str]) -> str:
pass
class N(NamedTuple, M):
attr1: str
def m(self, it):
return self.attr1 + it
Run Code Online (Sandbox Code Playgroud)
当我现在尝试这样做时,我收到此错误:
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
Run Code Online (Sandbox Code Playgroud)
我知道我可以这样做:
from typing import *
from abc import ABC, abstractmethod
class M(ABC):
@abstractmethod
def m(self, it: Iterable[str]) -> str:
pass
class NT(NamedTuple):
attr1: str
class N(NT, …Run Code Online (Sandbox Code Playgroud) 我想在使用带有abc库的抽象类时提取 python 类名。不幸的是,我收到了 class name ABCMeta。
import abc
class A(abc.ABC)
pass
class B(A)
pass
print(A.__class__.__name__) # output: 'ABCMeta'
print(B.__class__.__name__) # output: 'ABCMeta'
print(str(A)) # output: "<class '__main__.A'>"
print(str(B)) # output: "<class '__main__.B'>"
Run Code Online (Sandbox Code Playgroud)
我希望我应该收到如下输出
print(A.__class__.__name__) # output: 'A'
print(B.__class__.__name__) # output: 'B'
Run Code Online (Sandbox Code Playgroud)
在str(A)和str(B)似乎让我假设类的名字可以从什么地方提取打印的类名。但尽管如此,我对str用来解析和获取类名不感兴趣。
有没有办法将 python 类标记为抽象或不可实例化,即使它的所有抽象方法都已实现?
class Component(ABC):
@abstractmethod
def operation(self) -> None:
pass
class Decorator(Component): # I would like this class to be abstract
def operation(self) -> None:
print("basic operation")
Run Code Online (Sandbox Code Playgroud)
我发现的唯一解决方法是在类中选择一些方法来同时具有实现和@abstractmethod装饰器,但是随后 python 需要子抽象类的派生者来重新实现该方法。
这也可以通过让子类调用来解决super(),但pylint抱怨这是一个无用的调用。
class Component(ABC):
@abstractmethod
def operation(self) -> None:
pass
class Decorator(Component): # I would like this class to be abstract
@abstractmethod
def operation(self) -> None:
print("basic operation")
class ConcreteDecorator(Decorator):
def operation(self) -> None: # python makes child class re-implement
super().operation() # pylint complains …Run Code Online (Sandbox Code Playgroud) abc ×10
python ×9
python-3.x ×2
abstract ×1
class ×1
exception ×1
namedtuple ×1
oop ×1
python-3.6 ×1
python-mock ×1
subclass ×1