繁体   English   中英

内部类方法应该返回值还是只修改实例变量?

[英]Should internal class methods return values or just modify instance variables?

我正在创建一个查询构建器类,该类将有助于从 URL 参数构建 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以便将其传递给 mongo 的find()函数。 在这样做时,我只是想知道是否有绝对正确的方法来确定_build_query是否应该返回一个字典或者它是否应该只修改self.query_dict 由于它是一种内部方法,我认为只需修改self.query_dict 有没有正确的方法(pythonic)来解决这个问题? 这只是愚蠢而不是重要的设计决定吗? 任何帮助表示赞赏。

修改self.query_dict完全self.query_dict因为面向对象编程的整个思想是方法可以修改对象的状态。 只要对象在方法完成后处于一致状态,就可以了。 _build_query是内部方法这一事实无关紧要。 您可以选择在__init__之后调用_build_query以在创建对象时构造查询。

该决定主要用于测试目的。 出于测试目的,单独测试每个方法很方便,而不必测试整个对象的状态。 但这不适用于这种情况,因为我们讨论的是内部方法,因此您可以单独决定何时调用该方法,而不是其他对象或其他代码。

最好返回一个值,因为它允许您将所有修改的属性保留在一个地方 ( __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 从实例方法返回self便于方法链接,因为每个返回值都允许对同一对象进行另一个方法调用:

foo.add_thing(x).add_thing(y).set_goal(42).execute()

这有时被称为“流畅的”API。

然而,虽然 Python 允许对不可变类型(如intstr进行方法链接,但它并没有为可变容器(如listset方法提供它——按设计——所以它可以说不是“Pythonic”为你自己的可变类型做这件事类型。 尽管如此,许多 Python 库确实具有“流畅”的 API。

缺点是这样的 API 会使调试变得更加困难。 由于您执行或不执行整个语句,因此您无法轻松地在语句的中间点看到对象。 当然,我通常发现print非常适合调试 Python 代码,所以我只会在任何我感兴趣的返回值的方法中抛出一个print

虽然对象的方法直接修改其状态是很常见的,但有时将对象作为其自己的“客户端”并通过(通常)私有访问方法间接访问自己是有利的。 在 Python 中,您可以使用内置的property()类/函数轻松完成此操作。

这样做提供了更好的封装和随之而来的好处(与实现细节隔离是主要的)。 然而,这样做可能不切实际,因为它需要太多额外的代码,而且通常速度较慢,这可能会对性能产生不可接受的负面影响——因此,通常必须根据这一理想情况进行权衡。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM