无聊之人--除了技术,还是技术,你懂得
分类: Python/Ruby
2011-08-14 21:36:37
6.6. Putting It All Together
Once again, all the dominoes are in place. You've seen how each line of code works. Now let's step back and see how it all fits together.
所有的多米诺模块又一次就位了。你已经都看到每一行代码的作用。现在我们一步一步的看,然后看它们如何工作。
Example 6.21. listDirectory
例6.21 显示目录
listDirectory is the main
attraction of this entire module. It takes a directory (like c:\music\_singles\ in
my case) and a list of interesting file extensions (like ['.mp3']), and
it returns a list of class instances that act like dictionaries that contain
metadata about each interesting file in that directory. And it does it in
just a few straightforward lines of code. listDirectory是整个模块最吸引人注意的地方。它接受一个目录(在本例中C:\music\_singles\)和一个有趣的文件扩展名列表(如[.mp3])作为参数,然后一个类实例所组成的列表,该列表的行为就如同字典。列表中包含了目录中每一个你所感兴趣的文件的元数据。完成这些工作该函数只需要几行代码就行。 As you saw in the previous section, this line of code gets a list of the full pathnames of
all the files in directory that have an interesting file extension
(as specified byfileExtList). 正如你在前一部分所看到的,该行代码获得了目录中所有文件的全文件名所组成的列表。这些文件都有你所感兴趣的文件扩展名(通过byfileExtList来说明)。 Old-school Pascal programmers
may be familiar with them, but most people give me a blank stare when I tell
them that Python supports nested functions --
literally, a function within a function. The nested function getFileInfoClass can
be called only from the function in which it is defined, listDirectory.
As with any other function, you don't need an interface declaration or
anything fancy; just define the function and code it. 先前学校的Pascal编程者对此可能非常熟悉,当我告诉他们Python支持嵌套函数的时候,大多人都对我示之一白眼。从字面意思上看,所谓嵌套函数就是函数内部包含函数。嵌套函数getFileInfo Class只能被定义它的函数listDirectory所调用。同其它的函数一样,你不必进行接口声明或是其它任何事情:只需要定义一个函数然后进行编码即可。 Now that you've seen the os module,
this line should make more sense. It gets the extension of the file (os.path.splitext(filename)[1]),
forces it to uppercase (.upper()), slices off the dot ([1:]), and constructs
a class name out of it with string formatting. So c:\music\ap\mahadeva.mp3 becomes .mp3 becomes .MP3 becomes MP3 becomesMP3FileInfo. 正如你在os模块中所看到的那样,该行代码的意义重大。它获取了文件的扩展名(os.path.splittext(filename)[1]),然后强强制转换成大写形式(.upper()),对点(dot)处进行进行切片([1:]),接着使用字符串格式构建一个类名字。因此c:\music\ap\mahadeva.mp3 becomes .mp3—>.mp3->.MP3->最后变成了MP3FileInfo. Having constructed the name of the
handler class that would handle this file, you check to see if that handler
class actually exists in this module. If it does, you return the class,
otherwise you return the base class FileInfo. This is a very important
point: this function returns a class. Not an instance of a class,
but the class itself. 在构建完能处理文件的处理类的名字以后,你应该检查处理类是否存在模块中。如果有,你返回该处理类,如果不存在,你返回基类FileInfo。这点非常重要:该函数返回一个类。不是一个类实例,而是类本身。 For each file in the “interesting files”
list (fileList), you call getFileInfoClass with the filename (f).
Calling getFileInfoClass(f) returns a class; you don't know exactly
which class, but you don't care. You then create an instance of this class
(whatever it is) and pass the filename (f again), to the __init__ method.
As you saw earlier in this chapter, the __init__ method of FileInfo sets self["name"],
which triggers __setitem__, which is overridden in the descendant (MP3FileInfo)
to parse the file appropriately to pull out the file's metadata. You do all
that for each interesting file and return a list of the resulting instances. 在你所感兴趣的文件列表中的每一个文件,你使用文件名字filename来调用getFileInfoClass。对getFileInfoClass调用后,返回一个类:你不知道具体的类是何类,但是你不用担心。你接着创建了该类的一个实例(不论该类是何类)然后在一次将文件名字filename(f)传递给方法__init__.正如你在本章前面所看到的,FileInfo类的方法__init__设置self[“name”],这将触发__setitem__。该方法在后代类(MP3Fileinfo)中北重写,以用来解析适当的文件来抽取文件合适的元数据。你对所有的文件进行操作,然后返回包含结果的实例列表。
Note that listDirectory is completely generic. It doesn't know ahead of time which types of files it will be getting, or which classes are defined that could potentially handle those files. It inspects the directory for the files to process, and then introspects its own module to see what special handler classes (like MP3FileInfo) are defined. You can extend this program to handle other types of files simply by defining an appropriately-named class: HTMLFileInfo for HTML files, DOCFileInfo for Word .doc files, and so forth.listDirectory will handle them all, without modification, by handing off the real work to the appropriate classes and collating the results.
注意方法listDirectory是完全通用的。它先前不知道它将获得的文件的类型,或是那个类将被定义以用来处理这些文件。对被处理文件所在的目录进行内省,然后对自己模块进行外省以确定那个特定的处理类(如MP3Fileinfo类)是如何定义的。你可以扩展该程序好让它用来处理其他类型,比如通过定义一个合适的命名类,HTMLFileInfo用来处理HTML file,DOCFileInfo来处理word.doc文件等等listDirectory将会处理它们,而不必修改,然后实际的工作将被转换到合适的类和自动对应的结果