如何声明哪些方法可以应用于哪些对象
我正在编写一个服务器应用程序,该功能是通过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'方法是什么?
到目前为止,我想出了以下思路:
- 做一个臃肿基地(抽象)类将必须对所有可能的方法和属性存根。这里的缺点是,随着项目的增长和新方法的增加,它应该单独更新;所有的孩子班都会有很多不相关的和未使用的东西。另外,并不能真正解决问题。
- 用
try...except
包装所有电话。看起来不稳定和'pythonic',并没有解决问题。 - 手动指定方法支持哪些类。随着项目的增长,不可维护,并且不会严格地告知目标类必须具有哪些属性。
- 多重继承。修正了#3的问题,当使用修复方法创建新的
FixAllRobot
类时,我们可能会忘记添加目标检查所需的pro
属性。缺点:class Person(Inspecter, Fixer, ..., TwentyMoreOneFunctionHolder)
看起来不值得信赖和可读。而且我们仍然需要检查是否可以针对目标使用行动。 - 非常像#4,但也继承了目标端类。缺点:继承地狱:
class Person(Inspecter, CanBeInspected, Fixer, ..., FortyMoreOneFunctionHolder)
。优点:看起来像一个解决方案。
注:
关于检查和检查(和其它动作对):对于两个对象和对象时动作被称作必须作出一些类别相关的动作。
现在,相同类的所有对象都存储在它们的类字典中,其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
我建议用try...except
方法去。 EAFP(根据https://docs.python.org/2/glossary.html#term-eafp被认为是pythonic)“容易要求宽恕而不是许可”。随着项目的发展,它也很好地扩展。
我的美感告诉我,包装每一个方法调用尝试...除了不好看。并在文档中指出每种新方法也应该这样做看起来很糟糕。 – mFoxRU
你的问题没有多大意义。除限制异常外,限制**实际上可以做什么? Python已经通过引发'AttributeError'来做正确的事情,所以没有任何问题需要解决。您所需要做的就是为您的API提供适当的文档。 – ekhumoro
这不是关于使用限制,而更多的是关于设计其核心的方式,它显然应该做些什么来正确添加新功能,比如zope.interface。 – mFoxRU
您给出的“问题”示例具体是使用限制 - 即使用错误的参数类型调用“john.fix”。 – ekhumoro