steverippl
steverippl

Reputation: 378

Composing functionality into a method

I have something written in Perl/Moose that uses method modifiers (before/after/around) and I'm wondering what the "Pythonic" way of composing functionality into a method would be?

To expand, I have a data structure that needs to be processed, data is "tagged" to mark it in terms of how it should be processed. I check those tags and then dynamically build my processor accordingly. Using Perl's Moose I can pull in the "traits" I need and then run a single method to process the data. Each "Role" I pull in assumes there's a "process" method and it just bolts it's functionality on with an after 'process' => sub { }. This way if I have a new type of data to deal with I can simply add another Role without having to touch any other code. All this specifically avoids any inheritance and is very simple to manage.

I thought about trying to recreate Moose's "method modifiers" using decorators and/or metaclasses, but I'm wondering what the idiomatic way would be in Python...

Thanks

Upvotes: 0

Views: 86

Answers (2)

steverippl
steverippl

Reputation: 378

Just to expand on @LukasGraf answer pulling in contexts dynamically... (in Python 3)

from contextlib import ExitStack

class Manager1():
    def __init__(self, data):
        self.data = data

    def __enter__(self):
        print("entering 1... (data=%s)" % self.data)
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("exiting 1... (data=%s)" % self.data)



class Manager2():
    def __init__(self, data):
        self.data = data

    def __enter__(self):
        print("entering 2... (data=%s)" % self.data)
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("exiting 2... (data=%s)" % self.data

contexts = [Manager2('test'), Manager1('test')]

with ExitStack() as stack:
    [ stack.enter_context(context) for context in contexts ]
    print('here')

generates...

entering 2... (data=test)
entering 1... (data=test)
here
exiting 1... (data=test)
exiting 2... (data=test)

Upvotes: 0

Lukas Graf
Lukas Graf

Reputation: 32640

I hardly know any Perl, but from looking at the first example in the MethodModifier docs, it seems to me context managers in Python would be the thing that most resembles Moose's method modifiers:

class MyContextManager(object):
    def __init__(self, data):
        self.data = data

    def __call__(self):
        print 'foo'

    def __enter__(self):
        print "entering... (data=%s)" % self.data
        # this will be bound to the name after the 'as' clause 
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print "exiting... (data=%s)" % self.data

with MyContextManager('bar') as manager:
    print "before"
    manager()
    print "after"

Output:

entering... (data=bar)
before
foo
after
exiting... (data=bar)

Unfortunately, documentation for context managers is a bit spread out:

Upvotes: 1

Related Questions