2008-09-01 13 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() 메서드를 얻은 방법을 파악하기가 매우 어려워 질 수 있습니다.