Skip to content

Instantly share code, notes, and snippets.

@manuphatak
Created September 20, 2015 22:08
Show Gist options
  • Save manuphatak/e74f1f5197b8947af933 to your computer and use it in GitHub Desktop.
Save manuphatak/e74f1f5197b8947af933 to your computer and use it in GitHub Desktop.
Class decorator that overrides default kwargs.
from functools import wraps
def defaults(method='__init__', **default_args):
"""Class decorator. Overrides method default arguments."""
def decorate(cls):
func = getattr(cls, method)
@wraps(func)
def wrapper(self, *args, **kwargs):
default_args.update(kwargs)
return func(self, *args, **default_args)
setattr(cls, method, wrapper)
return cls
return decorate
@manuphatak
Copy link
Author

Overrides defaults without polluting the class namespace.
Defaults can be overridden again at runtime.

For example:

class FooBase(object):
    def __init__(self, a=1):
        self.a = a


@defaults(a=2)
class Foo(FooBase):
    pass


f = Foo()
assert f.a == 2  # Pass
g = Foo(a=3)
assert g.a == 3  # Pass

Class Foo is equivalent to:

class Foo(FooBase):
    def __init__(self, **kwargs):
        default_args = dict(a=2)
        default_args.update(kwargs)
        super(Foo, self).__init__(**default_args)

More examples:

  • Note: It defaults to overriding __init__. But use the method keyword to override any method defaults.
  • Note: The decorator is stackable and decorated objects are subclass friendly.
@defaults(a=4, b=6)
@defaults(method='add', a=3, b=5)
class Bar(object):
    def __init__(self, a=1, b=2):
        self.a = a
        self.b = b
        print(self.a)
        print(self.b)
        self.add()

    def add(self, a=7, b=9):
        print('a', a)
        print('b', b)


b = Bar()
# print 4
# print 6
# print a 3
# print b 5

b.add(a=35)
# print a 35
# print b 5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment