继承父类中定义的装饰器

时间:2015-04-12 22:50:05

标签: python python-2.7 python-decorators

而不是试图详细解释,这段代码片段应该这样做。

def decorator(function):
    return lambda self: function(self) + 1

# imported from library
class A(object):
    # override
    def method_1(self):
        pass

    # override
    def method_2(self):
        pass

class B(A):
    def method_1(self):
        return 1

class C(B):
    @decorator
    def method_2(self):
        return 1

class D(B):
    @decorator
    def method_2(self):
        return 2

print C().method_1() # 1
print C().method_2() # 2
print D().method_2() # 3

效果很好,但由于decorator仅用于method_2,因此可能会将其拉入。

class B(A):
    def method_1(self):
        return 1

    @staticmethod
    def decorator(function):
        return lambda self: function(self) + 1

class C(B):
    @B.decorator
    def method_2(self):
        return 1

这有效,但我不清楚这是否真的更好。特别是Python是否将B.decorator视为恰好在B上定义的外部函数,或者C是否继承自B效率更高。

我真正想要的是在B上定义装饰器并在C上使用它的某种方式。

class C(B):
    @self.decorator
    def method_2(self):
        return 1

这不起作用。也许还有更好的选择吗?感谢。

1 个答案:

答案 0 :(得分:0)

除了没有理由将装饰定义移到课堂内部之外,正如评论中所指出的,还有一些澄清:

当您在装饰器定义中使用<body> <form id="MasterForm"> <table border="2" style="box-shadow: 20px 20px 10px #000000; background-color: white;" align="center"> <tr> <th> <p align="Left">Name : <sup><font color="red">*</font></sup> </p> </th> <td> <input type="text" name="product_name" placeholder="Product Name" size="59" title="Enter the name of the product"> </td> </tr> <tr> <th> <p align="Left">Description : <sup><font color="red">*</font></sup> </p> </th> <td> <table border="0"> <textarea name="product_desc" placeholder="Product Description" maxlength="300" rows="6" cols="61" title="Enter the Description of the product"></textarea> </table> </td> </tr> <tr> <th> <p align="Left">Size &amp; Weight<sup><font color="red">*</font></sup> </p> </th> <th> <table border="1"> <td title="Size 2.2"> <label> <input type="checkbox" name="twopointtwosize" value="2.2size" title="Size 2.2" onClick="codename(this)">2.2 <br> <input name="twopointtwosizeqty" type="text" disabled onKeyPress="return isNumberKey(event)" size="2" placeholder="QTY" maxlength="5"> </label> </td> <td title="Size 2.4"> <label> <input type="checkbox" name="twopointfoursize" value="2.4size" title="Size 2.4" onClick="codename(this)">2.4 <br> <input type="text" size="2" name="twopointfoursizeqty" placeholder="QTY" onKeyPress="return isNumberKey(event)" maxlength="5" disabled> </label> </td> <td title="Size 2.6"> <label> <input type="checkbox" name="twopointsixsize" value="2.6size" title="Size 2.6" onClick="codename(this)">2.6 <br> <input type="text" size="2" name="twopointsixsizeqty" placeholder="QTY" onKeyPress="return isNumberKey(event)" disabled maxlength="5"> </label> </td> <td title="Size 2.8"> <label> <input type="checkbox" name="twopointeightsize" value="2.8size" title="Size 2.8" onClick="codename(this)">2.8 <br> <input type="text" size="2" name="twopointeightsizeqty" placeholder="QTY" onKeyPress="return isNumberKey(event)" disabled maxlength="5"> </label> </td> <td title="Size 2.10"> <label> <input type="checkbox" name="twopointtensize" value="2.10size" title="Size 2.10" onClick="codename(this)">2.10 <br> <input type="text" size="3" name="twopointtensizeqty" placeholder="QTY" onKeyPress="return isNumberKey(event)" disabled maxlength="5"> </label> </td> <td style="border-style: none;"> <input type="text" placeholder="Weight" name="weight" size="8" maxlength="8" title="Enter the weight in Grams" onKeyPress="return isNumberKey(event)" style="height: 45px;"> </td> </table> </th> </tr> <tr> <th> <p align="Left">Color : <sup><font color="red">*</font></sup> </p> </th> <td id="colors"> <table> <td title="White Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="White" title="White Colour" value="white"><b title="White Colour">White</b> </label> </td> <td title="White/Red Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="White/Red" title="White/Red Colour" value="w/r"><b title="White/Red Colour">W/R</b> </label> </td> <td title="White/Green Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="White/Green" title="White/Green Colour" value="w/g"><b title="White/Green Colour">W/G</b> </label> </td> <td title="White/Blue Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="White/Blue" title="White/Blue Colour" value="w/b"><b title="White/Blue Colour">W/B</b> </label> </td> </table> <table> <td title="Red Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="Red" title="Red Colour" value="red"><b title="Red Colour">Red</b> </label> </td> <td title="Red/Green Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="Red/Green" title="Red/Green Colour" value="r/g"><b title="Red/Green Colour">R/G</b> </label> </td> <td title="Red/Blue Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="Red/Blue" title="Red/Blue Colour" value="r/b"><b title="Red/Blue Colour">R/B</b> </label> </td> </table> <table> <tr> <td title="Green Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="Green" title="Green Colour" value="green"><b title="Green Colour">Green</b> </label> </td> </tr> <tr> <td title="Green/Blue Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="Green/Blue" title="Green/Blue Colour" value="g/b"><b title="Green/Blue Colour">G/B</b> </label> </td> </tr> <tr> <td title="Blue Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="Blue" title="Blue Colour" value="blue"><b title="Blue Colour">Blue</b> </label> </td> <td title="Multi Colour" style="border-style: groove; box-shadow: 5px 5px 2px #3B3131;"> <label> <input type="checkbox" name="multicolor" title="Multi Colour" value="multicolor"><b title="Multi Colour">MultiColour</b> </label> </td> <td title="Select All" align="right" style="border-style: none;"> <input type="checkbox" name="checkall" title="Select All" onclick='checkedAll(this);'> </td> <td style="border-style: none;"><b title="Select All">All</b> </td> </tr> </table> </td> </tr> <tr> <th> <p align="Left">Price : <sup><font color="red">*</font></sup> </p> </th> <td> <table border="1"> <tr> <td> <input type="text" name="product_price" placeholder="Original" size="21" title="Enter The Original Price Of The Product" onkeypress="return isNumberKey(event)"> </td> <td> <input type="text" name="product_special_price" placeholder="Special" size="21" title="Enter The Special Price Of The Product (not necessary)" onkeypress="return isNumberKeyspecial(event)"> </td> </tr> </table> </td> </tr> <tr> <th title="Special Price Validity Dates;(note it is valid only if entered special price)"> <p align="Left">Special Date : <sup><font color="red">*</font></sup> </p> </th> <td title="Special Price Validity Dates;(note it is valid only if entered special price)"> <table border="0"> <tr> <th title="Special Price Validity Starting Date">Start Date:</th> <td> <input type="date" name="startingdate" min="2015-02-01"> <br> </td> </tr> <tr> <th title="Special Price Validity Ending Date">End Date:</th> <td> <input type="date" name="endingdate" min="2015-02-01"> <br> </td> </tr> <tr> <th> <font color="white" size="0">Hello</font> </th> </tr> <tr> <th> <font color="white" size="0">Hello</font> </th> </tr> </table> </td> </tr> <tr> <th title="Status(Should the Product be visible to the customers)"> <p align="Left">Status : <sup><font color="red">*</font></sup> </p> </th> <th> <label>Enable : <input type="radio" name="status" value="enable" title="Enable The Status"> </label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <label>Disable : <input type="radio" name="status" value="disable" title="Disable The Status"> </label> </th> </tr> <tr> <th title="Tax Class(which type of tax should be applied on the product)"> <p align="Left">Tax Class : <sup><font color="red">*</font></sup> </p> </th> <th> <label>Taxable : <input type="radio" name="tax" value="taxable" title="Taxable Goods"> </label>&nbsp;&nbsp;&nbsp; <label>Shipping : <input type="radio" name="tax" value="shipping" title="Shipping"> </label>&nbsp;&nbsp;&nbsp <label>None : <input type="radio" name="tax" value="None" title="None from both on the left"> </label> </th> </tr> <tr> <th> <input type="reset" name="reset" value="Reset" onclick="resetForm()" title="Reset All The Details"> </th> <th> <input type="submit" name="submit" value="Add Product" title="Add Product To The Inventory" style=" width: 33em;height: 2em; border:none; background: transparent; font-weight:bold; cursor:pointer;"> </th> </tr> </table> </form> </body>装饰器时,您将具有与在任何类主体外部定义的完全相同的行为。

如果您确实使用@staticmethod,就像在

中一样
@classmethod

不同之处在于装饰器被传递给它定义的类,作为第一个参数的对象。这可能是有用的,或者不是 - 请注意,装饰方法本身仍然是常规实例方法 - 除非你在装饰器主体内部使用 class B(A): @classmethod def decorator(cls, function): return lambda self: function(self) + 1 @classmethod装饰器,更改包装器它返回的功能。

至于效率:最有效率的#34;将装饰员留在任何一个班级的身体之外的事情就是这样 - 一个&#34; @ staticmethod&#34; defiend装饰器将是最小的 - 可能根本无法测量,但是应该在类创建上涉及两到三次属性访问(通常不会在应用程序的关键循环内) - 所以,不,没有不一样。

现在,它不是你要问的,但有人可以来这里寻找如何在子类中超越此方法时自动在超类中的方法中重新应用装饰器: 这不容易做到,但应该可以使用专门准备的装饰器(它将在包装方法上进行自我调整)