简体   繁体   中英

Partial method inheritance/decorator in python

I've noticed in my function I have quite a few similar lines of code at the start and the bottom of my functions, for example:

    def foo1():
        print('start')
        print('of ')
        print('a code')

        '''
        a lot of other code for the foo1
        '''

        print('end')
        print('of')
        print('the code')

    def foo2():
        print('start')
        print('of ')
        print('a code')

        '''
        a lot of other code for the foo2
        '''

        print('end')
        print('of')
        print('the code')

I could put the similar parts in different methods as shown bellow:

def foo_init():
    print('start')
    print('of ')
    print('a code')

def foo_end():
    print('end')
    print('of')
    print('the code')


def foo1():
    foo_init()
    '''
    a lot of other code for the foo1
    '''
    foo_end():

def foo2():
    foo_init()
    '''
    a lot of the other for the foo1
    '''
    foo_end():

So I'm wondering, if there are any better/smarter ways of doing it, maybe using class inheritance or for loop?

You can define a decorator

import functools
def inspect(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):

        print('start')
        print('of ')
        print('a code')

        value = func(*args, **kwargs)

        print('end')
        print('of')
        print('the code')

        return value
    return wrapper

Then use it simply:

@inspect
def my_func ( arg ) :
    # Do something
    print( "my_func is called with arg =" , arg) 

You can learn more and more about decorators: Primer on Python Decorators

In addition to a decorator, this is a use case for a context manager. There are several ways to define a context manager, but I'll show one that lets you use it as a decorator as well.

from contextlib import ContextDecorator


class context(ContextDecorator):
    def __enter__(self):
        print('start')
        print('of ')
        print('a code')

    def __exit__(self, *exc):
        print('end')
        print('of')
        print('the code')

Then you can write either

@context
def foo1():
    ...

or

def foo1():
    with context():
        ...

Depending on your specific needs, either a context manager or a decorator may be more appropriate.

maybe using class inheritance

In OO, this is the "template method" pattern:

class Base:
    def run(self, *args, **kw):
        print('start')
        print('of ')
        print('a code')

        value = self.method(*args, **kwargs)

        print('end')
        print('of')
        print('the code')

        return value


    def method(self, *args, **kw):
        return None


class Child(Base):
    def method(self, *args, **kw):
        return 42


c = Child()
c.run()

But I wouldn't advise using classes and inheritance when you don't need them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM