在python中组合2个类的函数

时间:2017-12-29 02:23:59

标签: python oop

我有以下代码:

import time

class output_letter():

    def output_a(self):
        print('a')
    def output_b(self):
        print('b')
    def output_c(self):
        print('c')
    .............
    def output_z(self):
        print('z')
class wait_time():

    def sleep_2(self):
        time.sleep(2)

out = output_letter()
out.output_a()

我想将class wait_time.sleep_2的功能添加到类output_letter的开头。作为一个例子,如果我要创建一个假设的课程"合并" ,我能做到

c=combined()
c.output_a # would wait 2 seconds and then print 'a'

问题在于我不想重写' output_letter'的所有功能,我只想为其所有功能添加相同的功能。

我不清楚如何做到这一点,或者如果继承或组合可以做到这一点。

5 个答案:

答案 0 :(得分:2)

我看到你可能想要根据DRY和SOLID原则解决2个单独的任务:

  1. 将来很多其他地方应用wait_time非常容易
  2. 保持output_letter尽可能干净和不可接触会很酷
  3. 所以这是我的想法:

    1。创建一个模块,允许您为所有方法应用装饰器:

    def for_all_methods(decorator):
        def decorate(cls):
            for attr in cls.__dict__:
                if callable(getattr(cls, attr)):
                    setattr(cls, attr, decorator(getattr(cls, attr)))
            return cls
        return decorate
    

    2。同样隔离模块中的wait_time

    from time import sleep
    
    class wait_time():
        @staticmethod
        def sleep_decorator(function):
            def wrapper(*args, **kwargs):
                #sleep(2)
                print("sleeping")
                return function(*args, **kwargs)
            return wrapper
    

    3。这就是你如何使用它

    @for_all_methods(wait_time.sleep_decorator)
    class output_letter():
    
        def output_a(self):
            print('a')
    
        def output_b(self):
            print('b')
    
        def output_c(self):
            print('c')
    
        def output_z(self):
            print('z')
    

    所以好处,我们实际上并没有触及构造函数或改变继承。我们所做的只是在类上面添加了一个装饰器,在必要时可以轻松启用或禁用。

    如果你想更进一步并防止直接处理原始类,你可以创建一个继承自原始类的子combined,并在其定义之上添加该装饰符。

    您可以尝试 DEMO

答案 1 :(得分:1)

您可以在output_letter中创建time.sleep的类实例作为属性,也可以在方法本身中调用import time class wait_time(): def sleep_2(self): time.sleep(2) class output_letter(): def __init__(self): self.wait = wait_time() def output_a(self): self.wait.sleep_2() print('a') def output_b(self): self.wait.sleep_2() print('b') def output_c(self): self.wait.sleep_2() print('c')

选项1:

class output_letter():
   def output_a(self):
      time.sleep(2)
      print('a')
    def output_b(self):
      time.sleep(2)
      print('b')
    def output_c(self):
      time.sleep(2)
      print('c')

选项2:

a = outout_letter()
t = wait_time()
t.sleep_2()
a.output_a()

编辑:关于您最近的评论和编辑,您可能只想创建两个实例并调用每个实例:

wait_time

此外,似乎您正在尝试输出输出的每个字母,并在最后使用目标字母进行方法调用。要缩短代码并实施__getattr__,您可以使用class Output_Letter: def __init__(self): self.t = wait_time() def __getattr__(self, name): def wrapper(): self.t.sleep_2() print name.split('_')[-1] return wrapper a = Output_Letter() a.output_c()

c

输出:

SELECT * FROM (
SELECT * FROM myDB order by ID desc LIMIT 10) order by ID

答案 2 :(得分:1)

您在示例中显示的所有类都不是非常好的OOP设计。当您的方法没有引用任何状态时,不需要类。如果你只想要一个命名空间,通常模块就更好了。

但如果你的问题实际上是关于如何结合多种功能的效果那么这并不重要。有很多方法可以做到这一点。函数是Python中的第一类对象,因此您可以将它们放在列表或词典中,或者根据需要将它们作为参数传递给其他函数。您还可以创建“函数工厂”,即返回新函数的函数。

以下是您可以使用它来构建所需的延迟字母书写功能的方法。我将函数结果存储在几个词典中,但如果需要,你可以用它们做一些不同的事情。

import itertools
import time

def letter_writer_factory(letter):
    """Return a function that prints the provided letter when it is called"""
    def func():
        print(letter)
    return func

def delay_factory(seconds):
    """Return a function that when called, waits for the specified time"""
    def delay():
        time.sleep(seconds)
    return delay

def function_sequencer_factory(*functions):
    """Return a function that calls each function argument in turn"""
    def caller():
        for func in functions:
            func()
    return caller

letters = 'abc'
delay_times = [2, 5, 10]
output_funcs = {c: letter_writer_factory(c) for c in letters}
delay_funcs = {t: delay_factory(t) for t in delay_times}
delayed_output_funcs = {(c, t): function_sequencer_factory(df, of)
                        for (c, of), (t, df) in itertools.product(output_funcs.items(),
                                                                  delay_funcs.items())}

#print c after waiting for 10 seconds:
delayed_output_funcs['c', 10]()

这当然是一个非常愚蠢的例子,但是这些函数式编程技术可以用来在某些情况下做一些实际有用的事情。

答案 3 :(得分:0)

以下代码可以实现您的目标。您可以在组合类中设置类变量以表示output_letter和wait_time。然后在组合类的内部,您可以访问其他类的所有属性和函数。

import time
class output_letter():
    def output_a(self):
        print('a')
    def output_b(self):
        print('b')
    def output_c(self):
        print('c')
class wait_time():
    def sleep_2(self):
        time.sleep(2)
class combined():
    ol = output_letter()
    wt = wait_time()
    def output_a(self):
        self.wt.sleep_2()
        self.ol.output_a()

def main():
    c=combined()
    c.output_a()

if __name__ == '__main__':
    main()

答案 4 :(得分:0)

您可以子类化多个类。在Python 3中:

<强>鉴于

import time


class Letter():
    "Print a letter."""
    def output_a(self):
        print('a')

    def output_b(self):
        print('b')

    def output_c(self):
        print('c')


class WaitTime():
    """Set a delay."""
    def sleep_2(self):
        time.sleep(2)

<强>代码

class Combined(Letter, WaitTime):
    """Combine methods."""
    def output_a(self):
        super().sleep_2()
        super().output_a()


combined = Combined()
combined.output_a()
# 'a'                                              # delayed output

这允许您保留原始课程。您只需在新的Combined类中调用它们。

<强>详情

Combined类将其他类混合在一起。 super() function调用这些高级类来根据类方法解析顺序访问它们的方法:

Combined.__mro__
# (__main__.Combined, __main__.Letter, __main__.WaitTime, object)

要在Python 2中工作,需要some adjustments

class Letter(object):
    ...

class WaitTime(object):
    ...

class Combined(Letter, WaitTime):

    def output_a(self):
        super(Combined, self).sleep_2()
        super(Combined, self).output_a()

次要注意:为了便于阅读,请为类使用CamelCase名称。类名通常是名词;函数通常是动词。