如何声明哪些方法可以应用于哪些对象

问题描述:

我正在编写一个服务器应用程序,该功能是通过RPC调用的。应用程序具有可以相互交互的对象。如何声明哪些方法可以应用于哪些对象

假定以下简化的例子:

  • 人员可以检查和修复,以及可以检查;
  • 汽车可以刹车,并且可以检查和固定。

直接实现¹(RPC超出范围):

class Car(object): 
    def __init__(self, broken=False): 
     self.name = 'car' 
     self.broken = broken 

    def breaks(self): 
     self.broken = True 
     print 'Car broke' 

    def inspected(self, by): 
     if by.pro: 
      if self.broken: 
       print '{}: It\'s a broken car'.format(by.name) 
      else: 
       print '{}: It\'s a working car'.format(by.name) 
     else: 
      print '{}: It\'s a car'.format(by.name) 

    def fixed(self, by): 
     if not self.broken: 
      print 'Car is not broken' 
     else: 
      self.broken = False 
      print by.name, 'fixed the car' 


class Person(object): 
    def __init__(self, name, pro=False): 
     self.name = name 
     self.pro = pro 

    def inspect(self, target): 
     target.inspected(by=self) 

    def fix(self, target): 
     target.fixed(by=self) 

    def inspected(self, by): 
     if self.pro: 
      print '{}: {} is a pro'.format(by.name, self.name) 
     else: 
      print '{}: {} is not a pro'.format(by.name, self.name) 

创建一些对象:

>>> car = Car() 
>>> john = Person('John', pro=True) 
>>> bob = Person('Bob', pro=False) 

现在,用户可以与他们进行互动²

>>> car.breaks() 
'Car broke' 
>>> john.inspect(car) 
"John: It's a broken car" 
>>> john.fix(car) 
'John fixed the car' 
>>> bob.inspect(john) 
'Bob: John is a pro' 

这里的问题,如果我们拨打john.fix(bob)那么我们会得到AttributeError: 'Person' object has no attribute 'fixed'

那么,声明/限制哪些方法可以应用于哪些对象的良好和/或'pythonic'方法是什么?

到目前为止,我想出了以下思路:

  1. 做一个臃肿基地(抽象)类将必须对所有可能的方法和属性存根。这里的缺点是,随着项目的增长和新方法的增加,它应该单独更新;所有的孩子班都会有很多不相关的和未使用的东西。另外,并不能真正解决问题。
  2. try...except包装所有电话。看起来不稳定和'pythonic',并没有解决问题。
  3. 手动指定方法支持哪些类。随着项目的增长,不可维护,并且不会严格地告知目标类必须具有哪些属性。
  4. 多重继承。修正了#3的问题,当使用修复方法创建新的FixAllRobot类时,我们可能会忘记添加目标检查所需的pro属性。缺点:class Person(Inspecter, Fixer, ..., TwentyMoreOneFunctionHolder)看起来不值得信赖和可读。而且我们仍然需要检查是否可以针对目标使用行动。
  5. 非常像#4,但也继承了目标端类。缺点:继承地狱:class Person(Inspecter, CanBeInspected, Fixer, ..., FortyMoreOneFunctionHolder)。优点:看起来像一个解决方案。

注:

  1. 关于检查和检查(和其它动作对):对于两个对象和对象时动作被称作必须作出一些类别相关的动作。

  2. 现在,相同类的所有对象都存储在它们的类字典中,其ID为key。元类跟踪哪些类创建。用户通常只能控制一个对象。当用户发送可能看起来像{"jsonrpc": "2.0", "id": 77, "method": "inspect", "params": {"target": "car", "id": 1}}的RPC请求(实际上是json-rpc)时,将target解析为目标类,并将id作为实例标识符。一些可选参数也可能通过params字典传递。

旁注:我知道QT信号槽系统,并喜欢它,但我认为情况并非如此。

Sidenote2:我坚持到Python 2.7

+0

你的问题没有多大意义。除限制异常外,限制**实际上可以做什么? Python已经通过引发'AttributeError'来做正确的事情,所以没有任何问题需要解决。您所需要做的就是为您的API提供适当的文档。 – ekhumoro

+0

这不是关于使用限制,而更多的是关于设计其核心的方式,它显然应该做些什么来正确添加新功能,比如zope.interface。 – mFoxRU

+0

您给出的“问题”示例具体是使用限制 - 即使用错误的参数类型调用“john.fix”。 – ekhumoro

我建议用try...except方法去。 EAFP(根据https://docs.python.org/2/glossary.html#term-eafp被认为是pythonic)“容易要求宽恕而不是许可”。随着项目的发展,它也很好地扩展。

+0

我的美感告诉我,包装每一个方法调用尝试...除了不好看。并在文档中指出每种新方法也应该这样做看起来很糟糕。 – mFoxRU