2016-11-16 4 views
1

私は次のように私は、3クラスを作成したい、のpythonの初心者です:Python、どのようにクラスを作成するバッチですか?

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 

私はそれは恐ろしいことだと思います。だから私は次のようにしようとします:

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クラスを作成するバッチはありますか?

+0

第二の試みは動作しませんどのように**を教えてください。 'self(self .__ class__、self)' **は、 'self .__ class__'がサブクラス化されたときに正しいクラスではないので、無限の再帰エラーにつながることに注意してください。 –

+0

David Beazleyの[this](https://www.youtube.com/watch?v=sPiWg5jSoZI)トークに興味があるかもしれません。 –

答えて

2

ループは正しいアプローチですが、c(クラスの新しいグローバル名を設定しません)を再バインドしています。classステートメントでクラスに名前を付けるために変数を使用することはできませんc)、super(self.__class__, self)を使用するとlead to infinite recursion issuesとなります。

代わりにファクトリ関数を使用して、globals()辞書を使用して、新しく作成したクラスをグローバル名前空間に追加することができます。関数は、私たちはsuper()に実際のクラスオブジェクトを渡すことができますクロージャを提供します。

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) 

super(LoginCls, self)式は親関数の名前空間に非ローカル名としてLoginClsを見つけたので、いつも見つけるための正しいコンテキストを使用していますMROの次のクラス。

ファクトリ関数と_login_class_name、および_baseの名前がモジュールの実装の詳細であることを示すために、先頭にアンダースコアの名前を使用しました。

デモ:

>>> 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 
関連する問題