我知道之前已经问过这个问题,但我发现自己遇到了静态方法最合适的情况,但是还需要在这个类中引用一个实例变量。举个例子,假设我有以下类:
> mydf
name col1 col1
1 A 1.373546 NA
2 B 2.183643 8.0235623
3 C 1.164371 NA
4 D 3.595281 5.7796865
5 E 2.329508 3.7575188
6 F 1.179532 NA
7 G 2.487429 0.5706002
8 H 2.738325 7.2498618
9 I 2.575781 NA
10 J 1.694612 4.9101328
现在假设我有一些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')。
我有什么理由试图找到一种方法来做我正在思考的事情,还是我弄得一团糟?
更新 我认为评论很有帮助,我也认为这是我遇到的一个问题,因为设计不好。
该问题最初是作为一种防止并发访问HDF5文件的方法,它通过为每个类实例提供一个rlock,我可以将其用作上下文管理器,以防止任何其他尝试在文件使用时访问该文件。每个类实例都拥有它自己获得的rlock,并在完成所需的任何操作时释放。我还使用@staticmethod来执行一个例程,然后生成一个文件,该文件被传递给它自己的 init (),并且对每个类实例都是唯一的。当时看起来很聪明,但我后悔了。我还认为我完全不确定@staticmethods何时适合并且可能使它与@classmethods混淆,但是类变量将不再使我的类实例独有的rlock和文件成为可能。我想我应该更多地考虑设计与试图证明使用类定义的合理性,我并没有真正理解它以防止它被设计的方式。
答案 0 :(得分:3)
如果您认为自己一直遇到静态方法最合适的情况,那么您可能错了 - 对它们的良好用途非常罕见。如果你的静态方法需要访问实例变量,你肯定 错误。
staticmethod无法直接访问实例变量。没有班级的实例,或数千;您可以从哪个访问变量?
您尝试做的是创建一个新实例,只是为了访问其实例变量。这可能偶尔会有用 - 虽然它通常是一个好兆头,你首先不需要上课。 (并且,当它有用时,它通常非常不合适,通常让调用者写 mydf$col2 <- NA
mydf$col2[match(names(a), rownames(mydf))] <- a
而不是ExampleClass().doSomethingWithFiles
。)
这是合法的,但你只需要调用类,而不是调用它的ExampleClass.doSomethingWithFiles
方法。 __init__
永远不会返回任何东西;它接收已经创建的__init__
并修改它。如果你真的想要,你可以调用它的self
方法,但这实际上只是意味着调用类。 (在他们与之不同的次要方式中,它会调用你想要的课程。)
此外,一旦你有了一个实例,你可以正常使用它;你不需要查看它的__new__
。 (即使您只将属性名称作为字符串变量,__dict__
几乎总是您想要的,而不是getattr(obj, name)
。)
所以:
obj.__dict__[name]
那么,你该怎么做呢?
好吧,看看你的设计。 file_1 = __class__().file_name
实例唯一做的是保存文件名,该文件名具有默认值。你不需要一个对象,只需要传入一个普通的旧字符串变量,或者存储为全局变量。 (你可能听说全局变量很糟糕 - 但伪装的全局变量同样糟糕,并且还有其他问题,他们会变相伪装。这基本上就是你设计的。有时,全局变量是正确的答案。)
答案 1 :(得分:0)
也许我误解了你的意图,但我认为你误用了默认参数。
您似乎正在尝试使用'defaultFilename'
作为默认参数值。为什么不跳过尴尬的
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
并按如下方式更改功能
def doSomethingWithFiles(file_2, file_1='defaultFilename'):
如果对该值进行硬编码会让您感到不舒服,请尝试
class ExampleClass(object):
DEFAULT_FILE_NAME = 'defaultFilename'
def __init__(self, filename=DEFAULT_FILE_NAME):
self.file_name = filename
@staticmethod
def doSomethingWithFiles(file_2, file_1=DEFAULT_FILE_NAME):
with open(file_1, 'r') as f1, open(file_2, 'w') as f2:
# do magic in here
def moreMethodsThatUseSelf(self):
pass
但是,一般情况下,如果要在静态方法中访问实例变量,则可能错误地将问题建模。
答案 2 :(得分:0)
为什么不将实例作为参数输入到静态方法。我希望这段代码会有所帮助。
class ClassA:
def __init__(self, fname):
self.fname = fname
def print(self):
print('fname=', self.fname)
@staticmethod
def check(f):
if type(f)==ClassA :
print('f is exist.')
f.print()
print('f.fname=', f.fname)
else:
print('f is not exist: new ClassA')
newa = ClassA(f)
return newa
a=ClassA('temp')
b=ClassA('test')
ClassA.check(a)
ClassA.check(b)
newa = ClassA.check('hello')
newa.print()
答案 3 :(得分:0)
您不能从静态方法引用实例属性。假设存在多个实例,您可以从哪个实例中选择属性?
您似乎需要具有类属性和类方法。您可以使用classmethod
装饰器定义一个。
class ExampleClass(object):
file_name = 'foo'
@classmethod
def doSomethingWithFiles(cls, file_2, file_1 = None):
file_1 = cls.file_name
# Do stuff