python, how to batch create class?
我是Python的新手,我想创建3个类,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | class ProtectTemplate(TemplateView): @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(ProtectTemplate, self).dispatch(*args, **kwargs) def get_context_data(self, **kwargs): context['phone'] = xxx return context class ProtectList(ListView): @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(ProtectList, self).dispatch(*args, **kwargs) def get_context_data(self, **kwargs): context['phone'] = xxx return context class ProtectDetail(DetailView): @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(ProtectDetail, self).dispatch(*args, **kwargs) def get_context_data(self, **kwargs): context['phone'] = xxx return context |
我觉得很糟糕。所以我试着这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | login_class = [ ('ProtectTemplate', TemplateView), ('ProtectList', ListView), ('ProtectDetail', DetailView), ] for c, v in login_class: class c(v): @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(self.__class__, self).dispatch(*args, **kwargs) def get_context_data(self, **kwargs): context['phone'] = xxx return context |
但它不起作用。是否仍要批量创建3类?
您的循环是正确的方法,但是您正在重新绑定
您可以使用工厂函数,然后使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | def _create_login_class(name, base): class LoginCls(base): @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(LoginCls, self).dispatch(*args, **kwargs) def get_context_data(self, **kwargs): context['phone'] = xxx return context LoginCls.__name__ = name LoginCls.__qualname__ = name # Python 3 return LoginCls _login_class = [ ('ProtectTemplate', TemplateView), ('ProtectList', ListView), ('ProtectDetail', DetailView), ] for _name, _base in _login_class: globals()[_name] = _create_login_class(_name, _base) |
我使用了前导下划线名称来表示工厂函数和
演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | >>> class Base: ... def dispatch(self, *args, **kwargs): print('Base.dispatch({}, {}) called'.format(args, kwargs)) ... >>> class TemplateView(Base): pass ... >>> class ListView(Base): pass ... >>> class DetailView(Base): pass ... >>> method_decorator = lambda *args: lambda f: f >>> xxx = 'xxx' >>> login_required = 'login_required' >>> def _create_login_class(name, base): ... class LoginCls(base): ... @method_decorator(login_required) ... def dispatch(self, *args, **kwargs): ... return super(LoginCls, self).dispatch(*args, **kwargs) ... def get_context_data(self, **kwargs): ... context['phone'] = xxx ... return context ... LoginCls.__name__ = name ... LoginCls.__qualname__ = name # Python 3 ... return LoginCls ... >>> _login_class = [ ... ('ProtectTemplate', TemplateView), ... ('ProtectList', ListView), ... ('ProtectDetail', DetailView), ... ] >>> for _name, _base in _login_class: ... globals()[_name] = _create_login_class(_name, _base) ... >>> ProtectTemplate <class '__main__.ProtectTemplate'> >>> class SubclassDemo(ProtectTemplate): ... def dispatch(self, *args, **kwargs): ... print('SubclassDemo.dispatch({}, {}) called'.format(args, kwargs)) ... super(SubclassDemo, self).dispatch(*args, **kwargs) ... >>> SubclassDemo().dispatch(42, spam='ham') SubclassDemo.dispatch((42,), {'spam': 'ham'}) called Base.dispatch((42,), {'spam': 'ham'}) called |