gpt4 book ai didi

python - 在 python 中使用静态方法 - 最佳实践

转载 作者:太空狗 更新时间:2023-10-29 17:21:37 26 4
gpt4 key购买 nike

什么时候以及如何在 python 中使用静态方法?我们已经建立了使用类方法作为工厂方法来创建对象实例的方法,应该尽可能避免。换句话说,将类方法用作替代构造函数并不是最佳实践(参见 Factory method for python object - best practice)。

假设我有一个类用于表示数据库中的某些实体数据。假设数据是一个包含字段名称和字段值的 dict 对象,其中一个字段是使数据唯一的 ID 号。

class Entity(object):
def __init__(self, data, db_connection):
self._data = data
self._db_connection

这里我的 __init__ 方法获取实体数据 dict 对象。假设我只有一个 ID 号,我想创建一个 Entity 实例。首先,我需要找到其余数据,然后创建我的 Entity 对象的实例。根据我之前的问题,我们确定应该尽可能避免使用类方法作为工厂方法。

class Entity(object):

@classmethod
def from_id(cls, id_number, db_connection):
filters = [['id', 'is', id_number]]
data = db_connection.find(filters)
return cls(data, db_connection)

def __init__(self, data, db_connection):
self._data = data
self._db_connection


# Create entity
entity = Entity.from_id(id_number, db_connection)

以上是不该做什么或至少不该做什么(如果有其他选择)的示例。现在我想知道是否编辑我的类方法以使其更像是一种实用方法而不是工厂方法是一个有效的解决方案。换句话说,以下示例是否符合使用静态方法的最佳实践。

class Entity(object):

@staticmethod
def data_from_id(id_number, db_connection):
filters = [['id', 'is', id_number]]
data = db_connection.find(filters)
return data


# Create entity
data = Entity.data_from_id(id_number, db_connection)
entity = Entity(data)

还是使用独立函数从 ID 号中查找实体数据更有意义。

def find_data_from_id(id_number, db_connection):
filters = [['id', 'is', id_number]]
data = db_connection.find(filters)
return data


# Create entity.
data = find_data_from_id(id_number, db_connection)
entity = Entity(data, db_connection)

注意:我不想更改我的 __init__ 方法。以前人们建议让我的 __init__ 方法看起来像这样 __init__(self, data=None, id_number=None) 但可能有 101 种不同的方法来找到实体数据,所以我宁愿在某种程度上将逻辑分开。有道理吗?

最佳答案

When and how are static methods suppose to be used in python?

油嘴滑舌的回答是:不经常。

即使是花言巧语但也不是那么无用的答案是:当它们使您的代码更具可读性时。


首先,让我们绕道the docs :

Static methods in Python are similar to those found in Java or C++. Also see classmethod() for a variant that is useful for creating alternate class constructors.

所以,当您需要 C++ 中的静态方法时,您也需要 Python 中的静态方法,对吗?

嗯,不。

在 Java 中,没有函数,只有方法,因此您最终会创建伪类,这些伪类只是一堆静态方法。在 Python 中做同样的事情的方法是只使用自由函数。

这很明显。然而,尽可能努力地寻找一个合适的类来嵌入一个函数是好的 Java 风格,这样你就可以避免编写那些伪类,而做同样的事情是糟糕的 Python 风格——再一次,使用自由函数——这不太明显。

C++ 没有与 Java 相同的限制,但许多 C++ 风格无论如何都非常相似。 (另一方面,如果你是一个“现代 C++”程序员,并且内化了“自由函数是类接口(interface)的一部分”的习语,那么你对“静态方法在哪里有用”的直觉对于 Python 来说可能是相当不错的。)


但是,如果您是从第一原则出发,而不是从另一种语言出发,那么有一种更简单的方式来看待事物:

@staticmethod 基本上只是一个全局函数。如果你有一个函数 foo_module.bar() 如果拼写为 foo_module.BazClass.bar() 出于某种原因会更具可读性,请将其设为 @staticmethod。如果没有,不要。仅此而已。唯一的问题是建立你的直觉,让习惯的 Python 程序员更容易阅读。

当然,当您需要访问类而不是实例时,可以使用 @classmethod——正如文档所暗示的那样,替代构造函数是这种情况的范例。尽管您通常可以仅通过显式引用该类(尤其是当您没有太多子类时)使用@staticmethod 来模拟@classmethod ,你不应该。


最后,进入您的具体问题:

如果客户端需要通过 ID 查找数据的唯一原因是构造一个 Entity,那么这听起来像是您不应该公开的实现细节,而且它还会使客户端代码更加复杂.只需使用构造函数。如果你不想修改你的 __init__ (你是对的,你可能不想这样做是有充分理由的),请使用 @classmethod 作为替代构造函数: Entity.from_id(id_number, db_connection)

另一方面,如果在与 Entity 构造无关的其他情况下,该查找对客户端本身有用,那么这似乎与 无关Entity 类(或至少不超过同一模块中的任何其他内容)。所以,就让它成为一个免费的功能吧。

关于python - 在 python 中使用静态方法 - 最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15017734/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com