如何将类__init__参数限制为另一个类的列表?

时间:2017-10-24 16:41:19

标签: python oop

我有这四个课程。

class Button(object):
  def __init__(self):
    pass

  def invoke(self):
    return self.button_dict


class Template(object):
  def __init__(self):
    pass

  def message(self):
    message = {'attachment': { 'type': self.type }}
    message['attachment'].update(self.payload)

    return message


class URLButton(Button):
  def __init__(self, title, url):
    self.button_dict = {
      'type': 'web_url',
      'title': title,
      'url': url
    }


class ButtonTemplate(Template):
  def __init__(self, title, buttons):
    if (not all(isinstance(button, Button) for button in buttons)):
      raise ValueError('Invalid Buttons instances.')

    self.type = 'button'
    self.payload = {
      'title': title,
      'buttons': [
        button.invoke() for button in buttons
      ]
    }

呼叫...

ButtonList = [
  URLButton('Test URL 1', 'http://example.com'),
  URLButton('Test URL 2', 'http://example.com'),
  'Invalid button here'
]

print(ButtonTemplate('Test', ButtonList).message())

我有很多课期待 Button 实例的列表,我想在下面的所有类中避免这种验证:

if (not all(isinstance(button, Button) for button in buttons)):
    raise ValueError('Invalid Buttons instances.')

有没有办法强制参数成为实例列表? 什么是限制争论的更好方法?

工作代码段:https://repl.it/NJUv/2

1 个答案:

答案 0 :(得分:1)

您可以使用装饰器修改每个类'__init__()方法,从而减少锅炉板代码:

from functools import wraps

def validate_buttons_arg(func):
  """ Method decorator that makes sure buttons argument is a list of Button
      instances.
  """
  @wraps(func)
  def wrapper(self, title, buttons, *args, **kwargs):
    if (not all(isinstance(button, Button) for button in buttons)):
      raise ValueError('Invalid Buttons instances.')
    return func(self, title, buttons, *args, **kwargs)
  return wrapper


class ButtonTemplate(Template):
  @validate_buttons_arg  # Sample usage.
  def __init__(self, title, buttons):
    self.type = 'button'
    self.payload = {
      'title': title,
      'buttons': [
        button.invoke() for button in buttons
      ]
    }

也可以使用类装饰器或元类自动执行类似于应用它们的每个类的__init__()方法(而不是在它们之前手动添加@validate_button_arg行。 def __init__ S)。