如何在具有二进制操作的方法之间共享代码?

时间:2018-08-28 08:15:40

标签: python python-3.x

对不起,标题太简单了,请随时编辑更好的标题。

我想编写类似于以下代码的类似开关的方法(.on()off()):

class Hello:

    def on(self):
        self.say(1)

    def off(self):
        self.say(2)

    def say(self, param):
        # a lot of code common to .on() and .off()
        # specific code for .() and .off()
        if param == 1:
            print("hello")
        if param == 2:
            print("goodbye")
        # more code common to both cases

h = Hello()
h.on()
h.off()

.on().off()共享了很多我想重用的代码(=在方法之间不重复),但是上面的两阶段方法似乎比较笨拙。

是否存在更好的方法之间共享代码的方法?

我想到的另外两个想法(但不知道它们是否可以实现):

  • 一种包罗万象的方法,它将知道如何调用它并基于该方法做出决定
  • 一种告诉方法的方法:“在被调用时,执行 this (共享代码),然后运行下面的代码(特定代码),然后运行那个(再次,共享代码)”

3 个答案:

答案 0 :(得分:0)

我认为最Python化的方式是使用装饰器

from functools import wraps

def _say(func):
    @wraps(func)
    def inner(self, *args, **kwargs):
        print("set up")  # preprocessing code
        func(self, *args, **kwargs)  # unique code
        print("tear down")  # postprocessing code
    return inner

class Hello:

    @_say
    def on(self):
        print("hello")

    @_say
    def off(self):
        print("goodbye")

用法

Hello().on()
set up
hello
tear down

Hello().off()
set up
goodbye
tear down

请注意,innerfunc之间的通信数据将需要作为参数/返回值传递。


另一种经典方法是放弃单个方法,而只使用带有参数的方法(可能是布尔值,字符串或枚举),如下所示:

from enum import Enum

class State(Enum):
    OFF = 0
    ON = 1

class Hello:

    def say(self, state):
        print('set up')
        if state == State.ON:
            print('hello')
        elif state == State.OFF:
            print('goodbye')
        else:
            raise ValueError
        print('tear down')

答案 1 :(得分:0)

您可以在此处使用两种模式,一种是装饰器,另一种是上下文管理器:

让我们实现上下文管理器:

import contextlib

class Hello:

    def on(self):
      with self.say():
        print("hello")

    def off(self):
        with self.say():
          print("goodbye")

    @contextlib.contextmanager
    def say(self):
        # a lot of code common to .on() and .off()
        # specific code for .() and .off()
        print("before code")
        yield
        print("after code")
        # more code common to both cases

h = Hello()
h.on()
h.off()

通过实现说作为上下文管理器,它使我们可以轻松运行设置代码和拆卸代码。

答案 2 :(得分:0)

新尝试:

class wrap:

    before = "_before"
    after = "_after"

    def __init__(self, before=None, after=None):
        if before is not None:
            self.before = before
        if after is not None:
            self.after = after

    def __call__(self, func):
        def wrapper(wrapped_self, *a, **kw):
            getattr(wrapped_self, self.before)()
            result = func(self, *a, **kw)
            getattr(wrapped_self, self.after)()
            return result

        return wrapper


class Example:
    def _before(self):
        print("before")

    def _after(self):
        print("after")

    def say_done(self):
        print("done")

    @wrap()
    def hello(self, name):
        print("hi", name)

    @wrap(after="say_done")
    def goodbye(self, name):
        print("goodbye", name)


Example().hello("Woj")
Example().goodbye("Woj")