3

スタンドアロンの python アプリケーションでは、アプリケーションのアダプターを登録してアクセスするためにzope.interfacezope.componentパッケージを使用します。メタクラスの概念を使用して、メタクラスのinitメソッド内からアダプターを登録できると考えました。これにより、アダプターの登録プロセスが「自動化」されます。たとえば、zope パッケージがクラスに追加する属性を使用するなど、このアプローチに問題はありますか? ご意見をお寄せいただきありがとうございます。

from zope import component
from zope.interface import Interface, implements


class MetaclassAdapter(type):
    def __init__(cls, clsname, bases, attrs):
        super(MetaclassAdapter, cls).__init__(clsname, bases, attrs)
        component.provideAdapter(cls, cls.__component_adapts__, cls.__implements_advice_data__[0][0])


class IDocument(Interface):
  """Document interface."""

  def title():
    pass

  def author():
    pass

  def content():
    pass

class IPrinter(Interface):
  """Printer interface."""

  def write():
    """Print instance to ..."""


class Printer(object):
  """Adapt instances that provide IDocument interface to IPrinter.
  Print document's attributes to stdout.
  """

  __metaclass__ = MetaclassAdapter
  implements(IPrinter)
  component.adapts(IDocument)

  def __init__(self, context):
    """Store adapted instance that provides IDocument."""
    self.context = context

  def write(self):
    """Serialize document."""
    print 'author: ', self.context.author()
    print 'title: ', self.context.title()
    print 'content: ', self.context.content()



class TextDocument(object):
  implements(IDocument)

  def __init__(self, author, title, content):
    self._author = author
    self._title = title
    self._content = content

  def title(self):
    return self._title

  def author(self):
    return self._author

  def content(self):
    return self._content

# Create instance of TextDocument and store / serialize it to...
IPrinter(TextDocument("Leo T.", "Short Stories", "Once upon a time...")).write()
4

2 に答える 2

3

できるからといって、そうすべきだというわけではありません。

アダプターの登録は、クラス外の 1 行のコードであるため、メタクラスにビヘイビアーを組み込む代わりに、それを行うだけです。明示的は暗黙的よりも優れています。

于 2011-02-22T23:42:54.450 に答える
1

編集:@Tobuのアドバイスに従い、これをしないでください。以下の私の答えは正しくありませんが、完全を期すために残されています。zope.interface.implements メタクラス シャッフルがまだインターフェース情報を処理していないため、これは正しくありません。

アプローチは確かに正気だと思います。提供されたインターフェースまたは適合された仕様を提供する必要はありません。実装されているインターフェースが 1 つだけである限り、登録メソッドはそれらを把握します。

class MetaclassAdapter(type):
    def __init__(cls, clsname, bases, attrs):
        super(MetaclassAdapter, cls).__init__(clsname, bases, attrs)
        component.provideAdapter(cls)

(直接宣言または継承によって) 複数のインターフェースを実装するクラスをサポートする場合は、どのインターフェースがアダプター ターゲット インターフェースとして選択されるかを決定するためのセマンティクスを考え出す必要があります。

その場合は、provides= キーワード パラメータを使用して、選択したインターフェイスを registerAdapter に渡すだけです。クラスの内部データ構造から直接取得するのではなく、zope.interface イントロスペクション API (zope.interfaces.implementedBy) を使用して提供されたインターフェイスを見つけることをお勧めします。

于 2011-02-22T23:16:56.153 に答える