1

以下に、私がやろうとしていることの非常に簡単な例を示します。HTMLDecorator を他のクラスで使用できるようにしたいと考えています。デコレータと呼ばれるという事実は無視してください。これは単なる名前です。

import cgi

class ClassX(object):
  pass # ... with own __repr__

class ClassY(object):
  pass # ... with own __repr__

inst_x=ClassX()

inst_y=ClassY()

inst_z=[ i*i for i in range(25) ]

inst_b=True

class HTMLDecorator(object):
   def html(self): # an "enhanced" version of __repr__
       return cgi.escape(self.__repr__()).join(("<H1>","</H1>"))

print HTMLDecorator(inst_x).html()
print HTMLDecorator(inst_y).html()
wrapped_z = HTMLDecorator(inst_z)
inst_z[0] += 70
wrapped_z[0] += 71
print wrapped_z.html()
print HTMLDecorator(inst_b).html()

出力:

トレースバック (最新の呼び出しが最後):
  ファイル「html.py」の 21 行目
    print HTMLDecorator(inst_x).html()
TypeError: デフォルトの __new__ はパラメーターを取りません

私がやろうとしていることは可能ですか?もしそうなら、私は何を間違っていますか?

4

6 に答える 6

2

ジョンのソリューションは両方とも機能します。HTMLDecoratorを非常にシンプルでクリーンな状態に保つためのもう1つのオプションは、基本クラスとしてモンキーパッチを適用することです。これは、組み込みタイプではなく、ユーザー定義クラスに対してのみ機能します。

import cgi

class ClassX(object):
    pass # ... with own __repr__

class ClassY(object):
    pass # ... with own __repr__

inst_x=ClassX()
inst_y=ClassY()

class HTMLDecorator:
    def html(self): # an "enhanced" version of __repr__
        return cgi.escape(self.__repr__()).join(("<H1>","</H1>"))

ClassX.__bases__ += (HTMLDecorator,)
ClassY.__bases__ += (HTMLDecorator,)

print inst_x.html()
print inst_y.html()

ただし、注意が必要です。このようなモンキーパッチは、コードの可読性と保守性に高い代償を伴います。1年後にこのコードに戻ると、特にClassXが他のライブラリで定義されている場合、ClassXがそのhtml()メソッドをどのように取得したかを理解するのが非常に難しくなる可能性があります。

于 2008-09-01T08:30:41.247 に答える
2

非常に近いですが、ClassX からすべてを失います。以下は、同僚が私にくれたもので、トリックを実行しますが、恐ろしいものです. もっと良い方法があるはずです。

ある種のプロキシ オブジェクト スキームを設定しようとしているようです。それは実行可能であり、同僚よりも優れた解決策がありますが、最初に、いくつかの追加の方法にパッチを適用する方が簡単かどうかを検討してください。これは のような組み込みクラスでは機能しませんboolが、ユーザー定義のクラスでは機能します。

def HTMLDecorator (obj):
    def html ():
        sep = cgi.escape (repr (obj))
        return sep.join (("<H1>", "</H1>"))
    obj.html = html
    return obj

そして、ここにプロキシバージョンがあります:

class HTMLDecorator(object):
    def __init__ (self, wrapped):
        self.__wrapped = wrapped

    def html (self):
        sep = cgi.escape (repr (self.__wrapped))
        return sep.join (("<H1>", "</H1>"))

    def __getattr__ (self, name):
        return getattr (self.__wrapped, name)

    def __setattr__ (self, name, value):
        if not name.startswith ('_HTMLDecorator__'):
            setattr (self.__wrapped, name, value)
            return
        super (HTMLDecorator, self).__setattr__ (name, value)

    def __delattr__ (self, name):
        delattr (self.__wraped, name)
于 2008-09-01T07:33:45.487 に答える
0

@ジョン (37448):

申し訳ありませんが、名前であなたを誤解させた可能性があります (悪い選択)。私は実際にはデコレータ関数を探しているわけではなく、デコレータとはまったく関係ありません。私が求めているのは、html(self) 定義が ClassX または ClassY を使用することです__repr__。ClassX または ClassY を変更せずにこれを機能させたいと考えています。

于 2008-09-01T06:10:04.317 に答える
0

ああ、その場合、このようなコードが役立つのではないでしょうか? 実際にはデコレータとは何の関係もありませんが、引数をクラスの初期化関数に渡し、後でそれらの引数を取得する方法を示しています。

import cgi

class ClassX(object):
    def __repr__ (self):
        return "<class X>"

class HTMLDecorator(object):
    def __init__ (self, wrapped):
        self.__wrapped = wrapped

    def html (self):
        sep = cgi.escape (repr (self.__wrapped))
        return sep.join (("<H1>", "</H1>"))

inst_x=ClassX()
inst_b=True

print HTMLDecorator(inst_x).html()
print HTMLDecorator(inst_b).html()
于 2008-09-01T06:25:43.297 に答える
0

私がやろうとしていることは可能ですか?もしそうなら、私は何を間違っていますか?

それは確かに可能です。間違っているのは、HTMLDecorator.__init__()パラメーターを受け入れないことです。

簡単な例を次に示します。

def decorator (func):
    def new_func ():
        return "new_func %s" % func ()
    return new_func

@decorator
def a ():
    return "a"

def b ():
    return "b"

print a() # new_func a
print decorator (b)() # new_func b
于 2008-09-01T05:26:06.170 に答える
0

@ジョン (37479):

非常に近いですが、ClassX からすべてを失います。以下は、同僚が私にくれたもので、トリックを実行しますが、恐ろしいものです. もっと良い方法があるはずです。

import cgi
from math import sqrt

class ClassX(object): 
  def __repr__(self): 
    return "Best Guess"

class ClassY(object):
  pass # ... with own __repr__

inst_x=ClassX()

inst_y=ClassY()

inst_z=[ i*i for i in range(25) ]

inst_b=True

avoid="__class__ __init__ __dict__ __weakref__"

class HTMLDecorator(object):
    def __init__(self,master):
        self.master = master
        for attr in dir(self.master):
            if ( not attr.startswith("__") or 
                attr not in avoid.split() and "attr" not in attr):
                self.__setattr__(attr, self.master.__getattribute__(attr))

    def html(self): # an "enhanced" version of __repr__
        return cgi.escape(self.__repr__()).join(("<H1>","</H1>"))

    def length(self):
        return sqrt(sum(self.__iter__()))

print HTMLDecorator(inst_x).html()
print HTMLDecorator(inst_y).html()
wrapped_z = HTMLDecorator(inst_z)
print wrapped_z.length()
inst_z[0] += 70
#wrapped_z[0] += 71
wrapped_z.__setitem__(0,wrapped_z.__getitem__(0)+ 71)
print wrapped_z.html()
print HTMLDecorator(inst_b).html()

出力:

<H1>最良の推測</H1>
<H1><__main__.ClassY オブジェクト 0x891df0c></H1>
70.0
<H1>[141、1、4、9、16、25、36、49、64、81、100、121、144、169、196、225、256、289、324、361、400、441、484、 529、576]</H1>
<H1>はい</H1>
于 2008-09-01T06:55:13.317 に答える