【发布时间】:2018-09-11 06:28:22
【问题描述】:
我知道以前有人问过这个问题,但我发现自己遇到了最适合使用静态方法的情况,但还需要在此类中引用实例变量。例如,假设我有以下课程:
class ExampleClass(object):
def __init__(self, filename = 'defaultFilename'):
self.file_name = filename
@staticmethod
def doSomethingWithFiles(file_2, file_1 = None):
#if user didn't supply a file use the instance variable
if file_1 is None:
# no idea how to handle the uninitialized class case to create
# self.file_name.
file_1 = __class__.__init__().__dict__['file_name'] <--- this seems sketchy
else:
file_1 = file_1
with open(file_1, 'r') as f1, open(file_2, 'w') as f2:
.....you get the idea...
def moreMethodsThatUseSelf(self):
pass
现在假设我有几个带有不同文件名的 ExampleClass 实例(E1、E2、E3)传递到 __init__,但希望保留使用未初始化类 ExampleClass.doSomethingWithFiles(file_2 = E1.file_name, file_1) 的能力= E2.file_name) 或 E1.doSomethingWithFiles(file_2 = E2.file_name, file_1 = 'some_other_file') 视情况而定。
我有什么理由试图找到一种方法来做我在想的事情,还是我在搞砸?
更新 我认为 cmets 很有帮助,我也认为这是我遇到的一个问题,因为设计不好。
这个问题一开始是为了防止并发访问 HDF5 文件,方法是为每个类实例提供一个 rlock,我可以将其用作上下文管理器,以防止在文件正在使用时对其进行任何其他访问尝试。每个类实例都有它自己的 rlock,它在完成它需要做的任何事情后获取和释放。我还使用@staticmethod 来执行一个例程,然后生成一个文件,该文件被传递到它自己的 init() 中,并且对于每个类实例都是唯一的。当时觉得很聪明,但我后悔了。我还认为我完全不确定@staticmethods 何时合适,并且可能将它与@classmethods 混淆,但是类变量将不再使我的类实例独有的rlocks 和文件成为可能。我想我可能应该更多地考虑设计而不是试图用一个我并不真正理解的类定义来证明它是为了防止它被设计出来的。
【问题讨论】:
-
你搞得一团糟。存在静态方法的唯一原因是不允许您访问实例。听起来你只是想要一个普通的方法。
-
如果你得到答案,你应该接受它 - 如果它被 打开,如果其他人提出的问题与你的问题相似,它就不能用作建议的副本。
-
它们被认为是不必要的。事实上,它们是 Python 的一个相对较晚的补充。据我所知,包含它是为了安抚 Java 开发人员。
-
这是一个很好的使用静态方法的好例子(在标准库中多次看到):你有一个实例属性,它的值是一个函数,例如,
self.callback。现在你想为它提供一个默认值。类属性可以用作实例属性的默认值——但callback = lambda msg: None在类级别定义了一个方法,而不是一个函数。callback = staticmethod(lambda msg: None)避免了这种情况,并按预期为您提供了一个简单的功能。 (请注意,重点是 not 是一个方法,因此 not 有一个self。) -
@BrandonJ 糟糕的设计不是其他人的代码,而是我 6 个月或更长时间前的代码。我想重写它的方式当然是好的设计的定义——但仅限于前 6 个月。 :) 无论如何,如果你想了解更多关于类和静态方法的实际用途的信息,我有一篇几年前的不完整博客文章,我可以完成并链接到。但通过 grep 搜索标准库并查看核心开发人员如何使用它们可能更容易。
标签: python class variables instance static-methods