2008-09-01 10 views
0

以下私は何をしようとしているかの非常に簡単な例を持っています。他のクラスで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() 

出力:

Traceback (most recent call last): 
    File "html.py", line 21, in 
    print HTMLDecorator(inst_x).html() 
TypeError: default __new__ takes no parameters

は、私は可能何をしようとしていますか?もしそうなら、私は間違って何をしていますか?

答えて

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) 
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 
0

@ジョン(37448):

は、ここで簡単な例です

申し訳ありませんが、私は名前(悪い選択)であなたを誤解しているかもしれません。私は実際にデコレータ機能を探しているわけでも、デコレータとは何かを探しているわけでもありません。私が後にしているのは、html(self)defがClassXまたはClassYの__repr__を使用するためです。私はClassXまたはClassYを変更せずにこれを動作させたい。

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() 
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>Best Guess</H1> 
<H1><__main__.ClassY object at 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>True</H1>
2

ジョンのソリューションの両方が動作します。 HTMLDecoratorを非常に簡単できれいに保つことを可能にする別のオプションは、それを基本クラスとしてmonkey-patchすることです。これはまた、唯一のユーザー定義クラスではなく、組み込み型の作品:

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()メソッドをどのように持っているか把握するのが非常に難しくなります。

関連する問題