装饰器与带参数继承:如何将子类参数传入继承的装饰器
B to the Decorator Alright, let's work through this problem step by step. First, we'll fix a critical small issue in your original code, then adjust the decorator to properly access the B parameter from your foo instance.
Step 1: Fix the Parent Class Constructor Call
Your foo class inherits from bar, but bar's __init__ requires a val parameter. In your modified code, you're calling bar.__init__(self) without passing val—this will throw a TypeError. We'll use super() to correctly invoke the parent constructor and pass the required val along with your new B parameter.
Step 2: Adjust the Decorator to Access Instance B
Since your decorator wraps an instance method, the inner function of the decorator already receives the foo instance (as obj) as the first argument. This means you can directly access obj.B within the decorator's logic—no need to pass B to the decorator at definition time (since B is an instance-specific value that only exists when a foo object is created).
Complete Working Code
class bar(object): def __init__(self, val): self.val = val @staticmethod def decor(func): def increment(obj, x): # Access both parent class's val and foo instance's B return func(obj, x) + obj.val + obj.B return increment class foo(bar): def __init__(self, B, val): # Correctly call parent constructor with required val parameter super().__init__(val) self.B = B @bar.decor def add(self, x): return x # Test the implementation if __name__ == "__main__": # Create a foo instance with B=5 and val=10 foo_instance = foo(B=5, val=10) # Expected result: 3 + 10 +5 = 18 print(foo_instance.add(3)) # Output: 18
How It Works
- When you decorate
foo.addwith@bar.decor, the decorator replaces the originaladdmethod with theincrementfunction. - When you call
foo_instance.add(3), theincrementfunction runs: it calls the originaladdmethod (which returns3), then addsfoo_instance.val(10) andfoo_instance.B(5) to get the final result.
Alternative: Static B for All Instances
If you wanted B to be a fixed value for all foo instances (instead of instance-specific), you could modify the decorator to accept parameters:
class bar(object): def __init__(self, val): self.val = val @staticmethod def decor_with_B(B): def actual_decorator(func): def increment(obj, x): return func(obj, x) + obj.val + B return increment return actual_decorator class foo(bar): def __init__(self, val): super().__init__(val) # Use parameterized decorator with fixed B=5 @bar.decor_with_B(B=5) def add(self, x): return x
Note that this makes B a static value for all foo instances, which is likely not what you need since you added B as an instance parameter in foo.__init__.
内容的提问来源于stack exchange,提问作者Jackiemiao

