如何修饰构造函数具有参数的类?这是我的代码;
angular.module('app', ['ngMessages']);
这个想法是在基类中的dict中注册子类的实例。
当我运行代码时,我收到以下错误
# Base Class
class Model(object):
models = {}
def __init__(self):
pass
# decorator
def register(cls):
Model.models[cls.__name__] = cls()
#Subclasses
@register
class PaperModel(Model):
def __init__(self, paper):
self.paper = paper
@register
class WoodenModel(Model):
def __init__(self, wood):
self.wood = wood
但是,如果我删除子类(PaperModel& WoodenModel)构造函数中的参数,代码就可以工作。
答案 0 :(得分:4)
如果要注册带注释的子类的实例,注释必须返回一些将创建实例并注册它们的内容。
顺便说一下,如果你使用一个简单的字典,你只会注册每个子类的最后一个创建的实例。如果要注册所有实例,最好使用defaultdict(list)
以下是代码示例:
class Model(object):
models = collections.defaultdict(list)
def register(cls):
def registrar(*args, **kwargs):
# first create the instance with the passed parameters
instance = cls(*args, **kwargs)
# then register the instance and return it
Model.models[cls.__name__].append(instance)
return instance
return registrar
@register
class PaperModel(Model):
def __init__(self, paper):
self.paper = paper
此代码可以注册不同的实例:
>>> p1 = PaperModel('A4')
>>> p1
<__main__.PaperModel object at 0x02AA0FB0>
>>> p2 = PaperModel('A3')
>>> p2
<__main__.PaperModel object at 0x02AA0F10>
>>> Model.models
defaultdict(<type 'list'>, {'PaperModel': [<__main__.PaperModel object at 0x02AA0FB0>, <__main__.PaperModel object at 0x02AA0F10>]})
或者,您根本无法使用注释,并使用基类的特殊__new__
方法来获得相同的结果:
class Model(object):
models = collections.defaultdict(list)
def __new__(cls, *args, **kwargs):
inst = super(Model, cls).__new__(cls)
inst.__init__(*args, **kwargs)
Model.models[cls.__name__].append(inst)
return inst
class PaperModel(Model):
def __init__(self, paper):
self.paper = paper
此代码也可以注册实例:
>>> p1 = PaperModel('A4')
>>> p2 = PaperModel('A3')
>>> Model.models
defaultdict(<type 'list'>, {'PaperModel': [<__main__.PaperModel object at 0x02AA02D0>, <__main__.PaperModel object at 0x02AA03F0>]})
>>> Model.models['PaperModel'][0] is p1
True
>>> Model.models['PaperModel'][1] is p2
True
答案 1 :(得分:3)
只有在实例未实例化时才应注册实例:
def register(cls):
def wrapper(*args, **kwargs):
inst = cls(*args, **kwargs)
Model.models[cls.__name__] = inst
return inst
return wrapper
请注意,您还需要从装饰器返回该类,否则您的装饰者将返回None
,当您尝试在课程中使用装饰器时,您将获得TypeError
。
wm = WoodenModel('log')
print(wm)
# <__main__.WoodenModel object at 0x033A6730>
print(Model.models)
# {'WoodenModel': <__main__.WoodenModel object at 0x033A6730>}
答案 2 :(得分:2)
您需要instance
,即类的对象(不是类本身)要在基类中注册。更清洁的方法是在父类的__init__
中注册实例,因为子类是从它派生的。为此创建特定的装饰器是没有意义的。装饰器用于通用,例如,如果Parent类也是动态的。您的装饰者应该注册以下内容:<SomeClass>.models[<some_sub_class>]
以下是在父__init__
中注册的示例代码:
# update the entry the __init__() of parent class
class Model(object):
models = {}
def __init__(self):
Model.models[self.__class__.__name__] = self # register instance
class WoodenModel(Model):
def __init__(self, wood):
self.wood = wood
super(self.__class__, self).__init__() # Make a call to parent's init()
# Create a object
wooden_model_obj = WoodenModel(123)
print wooden_model_obj
# prints: <__main__.WoodenModel object at 0x104b3e990>
# ^
print Model.models
# prints: {'WoodenModel': <__main__.WoodenModel object at 0x104b3e990>}
# ^
# Both referencing same object
如果你想要一个通用装饰器来实现这一点,假设:
models
样本装饰器将如下:
def register(cls):
def register_wrapper(*args, **kwargs):
obj = cls(*args, **kwargs)
obj.__class__.__bases__[0].models[cls.__name__] = obj
# "obj.__class__.__bases__[0]" will return first inherited parent class
return obj
return register_wrapper
答案 3 :(得分:0)
您可以注册类型而不是实例(您不知道如何构造,您没有正确的参数可用):
Model.models[cls.__name__] = cls # note no parens