كيف يمكنني ببساطة أن أرث الأساليب من مثيل موجود؟

StackOverflow https://stackoverflow.com/questions/37479

سؤال

أدناه لدي مثال بسيط جدًا لما أحاول القيام به.أريد أن أكون قادرًا على استخدام 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

هل ما أحاول فعله ممكن؟إذا كان الأمر كذلك، ما الخطأ الذي أفعله؟

هل كانت مفيدة؟

المحلول

قريب جدًا، ولكن بعد ذلك أفقد كل شيء من 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)

نصائح أخرى

كلا الحلين اللذين طرحهما جون سيعملان.هناك خيار آخر يسمح لـ HTMLDecorator بالبقاء بسيطًا ونظيفًا للغاية وهو تصحيحه كفئة أساسية.يعمل هذا أيضًا مع الفئات المعرفة من قبل المستخدم فقط، وليس الأنواع المضمنة:

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

كن حذرًا، على الرغم من ذلك - فإن التصحيح القردي مثل هذا يأتي بثمن باهظ من حيث سهولة القراءة وقابلية الصيانة للتعليمات البرمجية الخاصة بك.عندما تعود إلى هذا الرمز بعد عام، قد يصبح من الصعب للغاية معرفة كيف حصل ClassX على طريقة html()، خاصة إذا تم تعريف ClassX في بعض المكتبات الأخرى.

هل ما أحاول فعله ممكن؟إذا كان الأمر كذلك، ما الخطأ الذي أفعله؟

من الممكن بالتأكيد.ما هو الخطأ في ذلك 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

@ جون (37448):

آسف، ربما خدعتك بالاسم (اختيار سيء).أنا لا أبحث حقًا عن وظيفة ديكور، أو أي شيء يتعلق بالديكور على الإطلاق.ما أسعى إليه هو أن يستخدم html(self) def استخدام ClassX أو ClassY's __repr__.أريد أن يعمل هذا دون تعديل ClassX أو ClassY.

آه، في هذه الحالة، ربما يكون رمز مثل هذا مفيدًا؟ليس له أي علاقة بالديكورات، ولكنه يوضح كيفية تمرير الوسائط إلى وظيفة تهيئة الفصل واسترداد تلك الوسائط لوقت لاحق.

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

@ جون (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>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top