我想创建一个行为类似collections.defaultdict的类,而不使用用法代码指定工厂。例如: 而不是
class Config(collections.defaultdict):
pass
这样:
Config = functools.partial(collections.defaultdict, list)
这几乎可以,但
isinstance(Config(), Config)
失败。我打赌这个线索意味着还有更深层次的狡猾问题。那么有没有办法真正实现这个目标呢?
我也尝试过:
class Config(Object):
__init__ = functools.partial(collections.defaultdict, list)
答案 0 :(得分:10)
我认为没有一种标准方法可以做到这一点,但如果你经常需要它,你可以把你自己的小功能放在一起:
import functools
import collections
def partialclass(cls, *args, **kwds):
class NewCls(cls):
__init__ = functools.partialmethod(cls.__init__, *args, **kwds)
return NewCls
if __name__ == '__main__':
Config = partialclass(collections.defaultdict, list)
assert isinstance(Config(), Config)
答案 1 :(得分:3)
如果您确实需要通过isinstance
进行显式类型检查,您只需创建一个不太简单的子类:
class Config(collections.defaultdict):
def __init__(self): # no arguments here
# call the defaultdict init with the list factory
super(Config, self).__init__(list)
您将使用列表工厂和
进行无参数构造isinstance(Config(), Config)
也可以。
答案 2 :(得分:1)
我有一个类似的问题,但是还要求我的部分应用类的实例可以腌制。我以为我会分享最终的结果。
我通过窥视Python自己的collections.namedtuple
来调整了fjarri的答案。下面的函数创建一个可以腌制的命名子类。
from functools import partialmethod
import sys
def partialclass(name, cls, *args, **kwds):
new_cls = type(name, (cls,), {
'__init__': partialmethod(cls.__init__, *args, **kwds)
})
# The following is copied nearly ad verbatim from `namedtuple's` source.
"""
# For pickling to work, the __module__ variable needs to be set to the frame
# where the named tuple is created. Bypass this step in enviroments where
# sys._getframe is not defined (Jython for example) or sys._getframe is not
# defined for arguments greater than 0 (IronPython).
"""
try:
new_cls.__module__ = sys._getframe(1).f_globals.get('__name__', '__main__')
except (AttributeError, ValueError):
pass
return new_cls
答案 3 :(得分:0)
至少在 Python 3.8.5 中它只适用于 functools.partial
:
import functools
class Test:
def __init__(self, foo):
self.foo = foo
PartialClass = functools.partial(Test, 1)
instance = PartialClass()
instance.foo
答案 4 :(得分:0)
可以使用 *args
和 **kwargs
:
class Foo:
def __init__(self, a, b):
self.a = a
self.b = b
def printy(self):
print("a:", self.a, ", b:", self.b)
class Bar(Foo):
def __init__(self, *args, **kwargs):
return super().__init__(*args, b=123, **kwargs)
if __name__=="__main__":
bar = Bar(1)
bar.printy() # Prints: "a: 1 , b: 123"