如果内部类方法的返回值或者只是修改实例变量?(Should internal class metho

2019-06-25 11:31发布

我创建一个查询生成器类,将在构造查询从网址参数的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化)的方式? 这只是愚蠢的,而不是一个重要的设计决定? 任何帮助表示赞赏。

Answer 1:

返回的值是优选,因为它可以让你把所有的属性在一个地方(修改__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的清晰度。



Answer 2:

这是完全正常的修改self.query_dict面向对象的程序设计的整体思路是,方法可以修改对象的状态。 只要对象是一个方法结束后一致的状态,你的罚款。 事实上, _build_query是一个内部方法无所谓。 您可以选择呼叫_build_query在后__init__已经构建查询创建对象时。

该决定主要事项进行测试。 毛皮测试的目的,它的方便单独地测试每个方法,而不必测试整个对象的状态。 但是,这并不因为我们是在谈论一个内部方法,这样你就单独决定何时调用该方法,而不是其他物体或其他代码在这种情况下适用。



Answer 3:

如果你在所有返回任何东西,我建议self 。 返回self从实例方法是方便的方法链接,因为每个返回值允许在同一对象上的另一种方法调用:

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

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

然而,尽管Python允许方法链恒定类型,如intstr ,它不为可变容器等的方法,它提供listset -by设计,所以它可以说是没有“Python化”这样做对你自己的可变类型。 不过,大量的Python库确有“流畅”的API。

不利的一面是,这样的API可以使调试更难。 既然你执行整个语句或没有它,你不能很容易地看到在语句中的中间点的对象。 当然,我通常会发现print完全足够调试Python代码,所以我只是抛出一个print在其返回值我感兴趣的任何方法!



Answer 4:

虽然这是常见的用于对对象进行的方法来直接修改它的状态,它有时是有利的一个目的为它自己的“客户端”,并通过(通常)私人接入方式间接访问自己。 在Python中,你可以通过使用内置的创建很容易地做到这property()类/函数。

这样做提供了更好的封装 ,使用它遵循(绝缘从实现细节是主要的)好处。 但是这样做可能是不切实际的,因为它需要太多额外的代码,而且往往速度较慢,从而影响性能产生不利不可接受的量 - 这样的取舍可能往往要相对于这个理想做/。



文章来源: Should internal class methods return values or just modify instance variables?