在Python中,是否可以从staticmethod引用实例变量?

在Python中,是否可以从staticmethod引用实例变量?,python,class,variables,instance,static-methods,Python,Class,Variables,Instance,Static Methods,我知道以前有人问过这个问题,但我发现自己遇到了staticmethod最合适的情况,但是还需要在这个类中引用实例变量。例如,假设我有以下课程: class ExampleClass(object): def __init__(self, filename = 'defaultFilename'): self.file_name = filename @staticmethod def doSomethingWithFiles(file_2, file_1

我知道以前有人问过这个问题,但我发现自己遇到了staticmethod最合适的情况,但是还需要在这个类中引用实例变量。例如,假设我有以下课程:

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
类示例类(对象):
def _uuinit _uuu(self,filename='defaultFilename'):
self.file\u name=文件名
@静力学方法
def doSomethingWithFiles(文件2,文件1=无):
#如果用户未提供文件,请使用实例变量
如果文件_1为无:
#不知道如何处理未初始化的类案例来创建
#self.file\u名称。

file\u 1=\uuuuu class\uuuu.\uuuuu init\uuuuu()。\uuuuu dict\uuuuu['file\u name']也许我误解了您的意图,但我认为您误用了默认参数。 似乎您正试图使用
'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
如果硬编码该值使您不舒服,可以尝试

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

但是,一般来说,如果您想访问静态方法中的实例变量,那么您的问题建模可能是错误的。

如果您认为您不断遇到最适合使用静态方法的情况,那么您可能是错误的,它们的良好用途非常少。如果您的staticmethod需要访问实例变量,那么您肯定错了

staticmethod无法直接访问实例变量。该类不能有实例,也不能有数千个;你会从哪一个访问变量


您试图做的是创建一个新实例,只是为了访问它的实例变量。这有时是有用的,尽管这通常是一个好迹象,表明你一开始并不需要上课。(而且,当它有用时,通过让调用者编写
ExampleClass().doSomethingWithFiles
而不是
ExampleClass.doSomethingWithFiles
,它非常不寻常,通常值得发信号)

这是合法的,但您只需调用类,而不是调用它的
\uuuuu init\uuuu
方法。
\uuuu init\uuuu
从不返回任何内容;它接收一个已经创建的
self
,并对其进行修改。如果你真的想,你可以调用它的
\uuuuu new\uuuuu
方法,但这实际上意味着调用这个类同样的事情。(从它们的细微差别来看,这是在调用您想要的类。)

而且,一旦你有了一个实例,你就可以正常使用它;您不需要查看它的
\uuuuu dict\uuuuuu
。(即使您只将属性名称作为字符串变量,
getattr(obj,name)
几乎总是您想要的,而不是
obj.\uu dict\uuuu[name]

因此:


那么,你应该怎么做呢


好吧,看看你的设计。
ExampleClass
实例所做的唯一一件事就是保存一个具有默认值的文件名。您不需要对象,只需要传入一个普通的旧字符串变量,或者存储为全局变量。(你可能听说过全局变量是不好的,但伪装的全局变量同样不好,还有一个额外的问题,那就是它们是伪装的。这基本上就是你设计的。有时,全局变量是正确的答案。)

为什么不将实例作为参数输入静态方法呢。我希望这段代码会有帮助

 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()

不能从静态方法引用实例属性。假设存在多个实例,您将从哪个实例中选择属性

您似乎需要的是一个class属性和一个class方法。您可以使用
classmethod
decorator定义一个

class ExampleClass(object):
    file_name = 'foo'

    @classmethod
    def doSomethingWithFiles(cls, file_2, file_1 = None):
        file_1 = cls.file_name
        # Do stuff

你弄得一团糟。静态方法存在的唯一原因是不允许您访问该实例。听起来你只是想要一个普通的方法。如果你得到了一个答案,你应该接受它-如果它是开放的,如果其他人问的问题与你的问题足够相似,它就不能被用作建议的副本。它们被认为是不必要的。事实上,它们是Python的一个相对较晚的补充。据我所知,包含它是为了安抚Java开发人员。下面是一个很好地使用staticmethod的示例(在stdlib中多次看到):您有一个实例属性,其值是一个函数,例如,
self.callback
。现在您希望为它提供一个默认值。类属性可以用作实例属性的默认值,但在类级别定义的是方法,而不是函数
callback=staticmethod(lambda msg:None)
避免了这一点,并按预期提供了一个普通函数。(请注意,关键是不要成为一个方法,因此不要有一个
self
)@BrandonJ糟糕的设计不是每个人的代码,而是我6个月前或更长时间的代码。我想重写的方式当然是好设计的定义,但仅限于前6个月。:)无论如何,如果您想了解更多关于类和静态方法的实际用途的信息,我有一篇几年前的不完整博文,我可以完成并链接到。不过,浏览一下stdlib,看看核心开发人员如何使用它们可能会更容易。这是我的设计,随着时间的推移,它变得越来越丑陋。我添加了一个更新,希望能说明我是如何来到这里的。最初,filename是hdf5store句柄,实例变量之一是rlock。当时我认为我是谨慎的,因为我用并发读/写破坏了几个文件,但我没有想到在与它们相关联的类外实例中处理这些文件会有多困难。回到绘图板上。我提供了一个更新,为我如何/为什么进入这一领域提供了更好的理由。hdf5存储句柄和rlock是负责处理该文件的类所特有的,这似乎是个好主意,但速度很快
 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()
class ExampleClass(object):
    file_name = 'foo'

    @classmethod
    def doSomethingWithFiles(cls, file_2, file_1 = None):
        file_1 = cls.file_name
        # Do stuff