我创建一个查询生成器类,将在构造查询从网址参数的MongoDB帮助。 我从来没有比我其他人做了很多面向对象的编程,或者专为消费类,除了使用基本的语言结构,并使用内置的模型Django的。
所以我有这样QueryBuilder
类
class QueryHelper():
"""
Help abstract out the problem of querying over vastly
different dataschemas.
"""
def __init__(self, collection_name, field_name, params_dict):
self.query_dict = {}
self.params_dict = params_dict
db = connection.get_db()
self.collection = db[collection_name]
def _build_query(self):
# check params dict and build a mongo query
pass
现在_build_query
我会检查params_dict
和填充query_dict
以便通过它来蒙戈的find()
函数。 在这一过程中,我只是想知道是否有一个绝对正确的做法为是否_build_query
应该返回一个字典,或者是否应该只是修改self.query_dict
。 由于这是一个内部方法,我会假设它是确定只需修改self.query_dict
。 有接近此的一个正确的方式(Python化)的方式? 这只是愚蠢的,而不是一个重要的设计决定? 任何帮助表示赞赏。
返回的值是优选,因为它可以让你把所有的属性在一个地方(修改__init__
)。 另外,这使得它便于以后扩展的代码; 假设你想覆盖_build_query
在子类中,然后重写方法可以只返回一个值,而不需要知道哪个属性进行设置。 下面是一个例子:
class QueryHelper(object):
def __init__(self, param, text):
self._param = param
self._query = self._build_query(text)
def _build_query(self, text):
return text + " and ham!"
class RefinedQueryHelper(QueryHelper):
def _build_query(self, text):
# no need to know how the query object is going to be used
q = super(RefinedQueryHelper, self)._build_query()
return q.replace("ham", "spam")
主场迎战“二传手版”:
class QueryHelper(object):
def __init__(self, param, text):
self._param = param
self._build_query(text)
def _build_query(self, text):
self._query = text + " and ham!"
class RefinedQueryHelper(QueryHelper):
def _build_query(self, text):
# what if we want to store the query in __query instead?
# then we need to modify two classes...
super(RefinedQueryHelper, self)._build_query()
self._query = self._query.replace("ham", "spam")
如果你选择设置属性,你可能要调用的方法_set_query
的清晰度。
这是完全正常的修改self.query_dict
面向对象的程序设计的整体思路是,方法可以修改对象的状态。 只要对象是一个方法结束后一致的状态,你的罚款。 事实上, _build_query
是一个内部方法无所谓。 您可以选择呼叫_build_query
在后__init__
已经构建查询创建对象时。
该决定主要事项进行测试。 毛皮测试的目的,它的方便单独地测试每个方法,而不必测试整个对象的状态。 但是,这并不因为我们是在谈论一个内部方法,这样你就单独决定何时调用该方法,而不是其他物体或其他代码在这种情况下适用。
如果你在所有返回任何东西,我建议self
。 返回self
从实例方法是方便的方法链接,因为每个返回值允许在同一对象上的另一种方法调用:
foo.add_thing(x).add_thing(y).set_goal(42).execute()
这有时被称为“流畅”的API。
然而,尽管Python允许方法链恒定类型,如int
和str
,它不为可变容器等的方法,它提供list
和set
-by设计,所以它可以说是没有“Python化”这样做对你自己的可变类型。 不过,大量的Python库确有“流畅”的API。
不利的一面是,这样的API可以使调试更难。 既然你执行整个语句或没有它,你不能很容易地看到在语句中的中间点的对象。 当然,我通常会发现print
完全足够调试Python代码,所以我只是抛出一个print
在其返回值我感兴趣的任何方法!
虽然这是常见的用于对对象进行的方法来直接修改它的状态,它有时是有利的一个目的为它自己的“客户端”,并通过(通常)私人接入方式间接访问自己。 在Python中,你可以通过使用内置的创建很容易地做到这property()
类/函数。
这样做提供了更好的封装 ,使用它遵循(绝缘从实现细节是主要的)好处。 但是这样做可能是不切实际的,因为它需要太多额外的代码,而且往往速度较慢,从而影响性能产生不利不可接受的量 - 这样的取舍可能往往要相对于这个理想做/。
文章来源: Should internal class methods return values or just modify instance variables?