调用从方法返回的对象方法作为方法变量

时间:2016-07-27 18:14:09

标签: python python-3.x

我有一个列表,我将使用文件作为示例。需要以不同的方式处理每种类型的文件。我创建了一个类“MyFile”而不是维护一个巨大的if:elif:else:structure我创建了一个以文件类型为键的字典。它存储为类变量。

class MyFile(object):

    def process_xlsx(self):
        #process file stuff for Excel
        pass

    def process_docx(self):
        #process file stuff for Word
        pass

    def get_filetype(self):
        try: 
            return self.FileTypes[file_extension]
        except KeyError:
            return None #filetype not handled... yet

    FileTypes = {
        "XLSX": ("Excel File", process_xlsx), 
        "DOCX": ("Word   Document", process_docx)
        }

在不同的类/对象/模块中,我实例化MyFile类并开始逐步执​​行文件。 MyFile对象已正确创建。

f = MyFile("full_file_path_and_name")
file_type = f.get_filetype()

file_type有一个带有键的元组和一个函数对象。这是一个例子:     xls_0386.xlsx - ('Excel文件',)     doc_0386.docx - ('Word File',)

问题:如何调用从f.get_filetype()返回的函数?

file_type[1]()

返回:process_xlsx()缺少1个必需的位置参数:'self'

file_type[1]

不会创建错误,但实际上从不进行调用(在进程_ ????方法中永远不会达到断点)

再次,以这种方式调用对象方法的语法是什么?

我知道用我的细节解释这有点令人费解,为此我道歉。

提前致谢。

3 个答案:

答案 0 :(得分:1)

创建class时,您在其中定义的方法是只是函数。只有当您从类的实例中检索它们的名称时,它们才会绑定到该实例,从而生成绑定方法。这是通过descriptor protocol完成的。

因此,当您创建FileTypes词典时:

FileTypes = {
    "XLSX": ("Excel File", process_xlsx), 
    "DOCX": ("Word   Document", process_docx)
    }

这些是普通的功能。

您有三种选择,基本上:

  1. 不要在课程定义时创建字典。在创建实例时创建它,以便可以在其中存储绑定方法

    class MyFile(object):
        def __init__(self):    
            self.FileTypes = {
                "XLSX": ("Excel File", self.process_xlsx), 
                "DOCX": ("Word   Document", self.process_docx)
            }
    

    因为这会查找self上的方法,所以它们是绑定的。

  2. 手动绑定方法'当你在get_filetype()中查找时:

    def get_filetype(self):
        try: 
            return self.FileTypes[file_extension].__get__(self)  # binding!
        except KeyError:
            return None #filetype not handled... yet
    
  3. 返回functools.partial() object self作为位置参数而不仅仅是函数:

    from functools import partial
    
    def get_filetype(self):
        try: 
            return partial(self.FileTypes[file_extension], self)  # also a kind of binding
        except KeyError:
            return None #filetype not handled... yet
    
  4. 所有这三种方法都会导致一个对象被返回给调用者,当被调用时,它会将MyFile()的正确实例传递给所选择的函数。

答案 1 :(得分:0)

你用第一个参数调用它是你想要的自己。例如:

f = MyFile("full_file_path_and_name")
file_type = f.get_filetype()
file_type[1](f)

这样,您还可以使用该功能的任何其他文件。如果您只想使用file_type[1]调用特定文件,请使用部分填充的函数,因此self已经是参数。您可以使用functools.partial

执行此操作
import functools

class MyFile(object):

    # ...

    def get_filetype(self):
        def partial(func):
            return functools.partial(func, self)
        return {"XLSX": ("Excel File", partial(process_xlsx)),
                "DOCX": ("Word   Document", partial(process_docx))
               }.get(self.file_extension)

# Then you just do

f = MyFile("full_file_path_and_name")
file_type = f.get_filetype()
file_type[1]()

答案 2 :(得分:0)

因为这些函数是在类中声明的,所以它们具有参数self,表示该类中调用该函数的对象。当您尝试单独调用该函数时,在MyFile对象的上下文之外,不再有self变量与函数调用关联。这就是你收到错误的原因:

  

缺少1个必要的位置参数:' self'

只需将您已创建的MyFile实例作为self变量使用:

file_type[1](f)