2016-07-27 56 views
1

我有一个列表,我将使用文件作为示例。每种类型的文件需要以不同的方式处理。我创建了一个类“MyFile”,而不是维护一个巨人,如果: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 - (“字文件”)

问:我如何调用从f.get_filetype返回的功能( )?

file_type[1]() 

返回:process_xlsx()失踪1个人需要的位置参数: '自我'

file_type[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]() 
+0

正如你所知,这个工作完美!谢谢。我是Python的新手,我仍然试图让我的头脑中的一些细节。这为我填补了另一个。 此外,感谢您有关“部分”的更多信息。我会深入研究这一点,但这绝对是我认为我领导的地方。 很多荣誉。 – billbris

0

做到这一点,他们必须代表从类调用了函数的对象参数self。当您尝试在MyFile对象的上下文之外单独调用该函数时,不再有与​​该函数调用相关联的变量self。这就是为什么你的错误:

missing 1 required positional argument: 'self'

只要给它的MyFile实例,你已经创建为self变量来使用:

file_type[1](f) 
+0

谢谢。这是现货。我知道“自我”缺失,但没有经验知道从哪里得到它。现在我明白了。 – billbris

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() objectself作为一个位置参数,而不是仅仅的功能:

    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 
    

所有这三种方法都会导致一个对象返回给调用者,调用者在被调用时会通过t实例MyFile()到选定的功能。

+0

这也是非常正确的。我喜欢你已经布置的一些选项,并会考虑它们以及它们如何适合我的开发风格。非常感谢你的见解。他们相当有帮助。 – billbris