代码为:

"""Framework for getting filetype-specific metadata.

Instantiate appropriate class with filename.  Returned object acts like a
dictionary, with key-value pairs for each piece of metadata.
    import fileinfo
    info = fileinfo.MP3FileInfo("/music/ap/mahadeva.mp3")
    print "\\n".join(["%s=%s" % (k, v) for k, v in info.items()])

Or use listDirectory function to get info on all files in a directory.
    for info in fileinfo.listDirectory("/music/ap/", [".mp3"]):
        ...

Framework can be extended by adding classes for particular file types, e.g.
HTMLFileInfo, MPGFileInfo, DOCFileInfo.  Each class is completely responsible for
parsing its files appropriately; see MP3FileInfo for example.

This program is part of "Dive Into Python", a free Python book for
experienced programmers.  Visit http://diveintopython.org/ for the
latest version.
"""

__author__ = "Mark Pilgrim (mark@diveintopython.org)"
__version__ = "$Revision: 1.3 $"
__date__ = "$Date: 2004/05/05 21:57:19 $"
__copyright__ = "Copyright (c) 2001 Mark Pilgrim"
__license__ = "Python"

import os
import sys
from UserDict import UserDict

def stripnulls(data):
    "strip whitespace and nulls"
    return data.replace("\00", " ").strip()    #  .strip()移除字符串首尾在括号内指定参数的字符,默认为空格

class FileInfo(UserDict):
    "store file metadata"
    def __init__(self, filename=None):
        UserDict.__init__(self)
        self["name"] = filename
    
class MP3FileInfo(FileInfo):
    "store ID3v1.0 MP3 tags"
    tagDataMap = {"title"   : (  3,  33, stripnulls),
                  "artist"  : ( 33,  63, stripnulls),
                  "album"   : ( 63,  93, stripnulls),
                  "year"    : ( 93,  97, stripnulls),
                  "comment" : ( 97, 126, stripnulls),
                  "genre"   : (127, 128, ord)}
    
    def __parse(self, filename):
        "parse ID3v1.0 tags from MP3 file"
        self.clear()
        try:
            fsock = open(filename, "rb", 0)
            try:
                fsock.seek(-128, 2)
                tagdata = fsock.read(128)
            finally:
                fsock.close()
            if tagdata[:3] == 'TAG':
                for tag, (start, end, parseFunc) in self.tagDataMap.items():
                    self[tag] = parseFunc(tagdata[start:end])
        except IOError:
            pass

    def __setitem__(self, key, item):
        if key == "name" and item:
            self.__parse(item)
        FileInfo.__setitem__(self, key, item)

def listDirectory(directory, fileExtList):
    "get list of file info objects for files of particular extensions"
    fileList = [os.path.normcase(f) for f in os.listdir(directory)]    #os.path.normcase(f)表示转换f的大小写和斜杠;os.listdir(directory)列出 dir 里面
                                                                       #的所有文件和目录,但不包括子目录中的内容
    fileList = [os.path.join(directory, f) for f in fileList \         #path.join(directory, f)把目录和文件名合成一个路径;os.path.splitext(f)[1]分割路径,
                                                                       #返回路径名和文件扩展名的元组
                if os.path.splitext(f)[1] in fileExtList]
    def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]):
        "get file info class from filename extension"
        subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:] #进行大写转换
        return hasattr(module, subclass) and getattr(module, subclass) or FileInfo #hasattr(os, 'system')查看os对象是否有system属性,有返回True,否则False 
                                                                                   #getattr(os, 'system') 得到os对象的system属性
    return [getFileInfoClass(f)(f) for f in fileList]

if __name__ == "__main__":
    for info in listDirectory("E:\Kugou\Listen", [".mp3"]):
        print "\n".join(["%s=%s" % (k, v) for k, v in info.items()])
        print


输出为:
album=
comment=
name=E:\Kugou\Listen\makiyo - wake up.mp3
title=
artist=
year=
genre=12

album=needpop.com
comment=needpop.com
name=E:\Kugou\Listen\sara - 我的心好冷.mp3
title=我的心好冷(完整版)
artist=SARA needpop.com
year=2010
genre=255

album=⊙完美工作室⊙
comment=
name=E:\Kugou\Listen\三轮兄弟 斗地主 川普.mp3
title=斗地主(川普)
artist=三轮兄弟
year=
genre=0

album=绮楼ぁ听风雨收藏Qq:1505388177
comment=
name=E:\Kugou\Listen\付辛博 - 我,一个人.mp3
title=
artist=
year=
genre=255

name=E:\Kugou\Listen\伍佰、china blue - 心如刀割.mp3

name=E:\Kugou\Listen\冷漠 - 醉红颜.mp3

name=E:\Kugou\Listen\冷漠、云菲菲 - 小三.mp3

album=
comment=
name=E:\Kugou\Listen\凤凰传奇 - 大声唱.mp3
title=
artist=
year=
genre=12

解释与拓展:

>>> num
'i like pYthon'
>>> '  spacious   '.strip()
'spacious'
>>> 'www.example.com'.strip('comz.')
'www.example'
>>> 'www.example.com'.strip('comwz.')
'example'
>>> num.strip('on')
'i like pYth'
>>> num.strip('th')
'i like pYthon'
>>> 'www.example.com'.strip('comw.')
'example'
>>> 'www.example.com'.strip('comwe.')
'xampl'
>>> 'www.example.com'.strip('comwx.')
'example'
>>> 'www.example.com'.strip('lecomw.')
'xamp'
strip ()只是去除字符串首尾的第一个开始匹配的指定字符,第一次去除后若首尾还有指定字符,则继续去除,直到首尾无指定的参数,对中间的原样保留,

2、hasattr(os, 'system')查看os对象是否有system属性,有返回True,否则False ;getattr(os, 'system') 得到os对象的system属性

int PyObject_HasAttr ( PyObject  *o, PyObject  *attr_name )

Returns 1 if o has the attributeattr_name, and0 otherwise. Thisis equivalent to the Python expressionhasattr(o,attr_name). This functionalways succeeds.

int PyObject_HasAttrString ( PyObject  *o, const char  *attr_name )

Returns 1 if o has the attributeattr_name, and0 otherwise. Thisis equivalent to the Python expressionhasattr(o,attr_name). This functionalways succeeds.

PyObject* PyObject_GetAttr ( PyObject  *o, PyObject  *attr_name )
Return value: New reference.

Retrieve an attribute named attr_name from object o. Returns the attributevalue on success, orNULL on failure. This is the equivalent of the Pythonexpressiono.attr_name.

PyObject* PyObject_GetAttrString ( PyObject  *o, const char  *attr_name )
Return value: New reference.

Retrieve an attribute named attr_name from object o. Returns the attributevalue on success, orNULL on failure. This is the equivalent of the Pythonexpressiono.attr_name.

from 模块名 import 模块名
from UserDict import UserDict

它与你所熟知的 import module 语法很相似,但是有一个重要的区别:UserDict 被直接导入到局部名字空间去了,所以它可以直接使用,而不需要加上模块名的限定。你可以导入独立的项或使用frommodule import * 来导入所有东西。 

比较 import 模块名

>>> import odbchelper                              
>>> params = {"server":"mpilgrim", "database":"master", "uid":"sa", "pwd":"secret"}
>>> print odbchelper.buildConnectionString(params)   #加上模块名
使用在被导入模块中定义的函数时,必须包含模块的名字。所以不能只使用 buildConnectionString,而应该使用 odbchelper.buildConnectionString

注意
Python 中的frommodule import *Perl 中的usemodulePython 中的importmodulePerl 中的requiremodule
注意
Python 中的frommodule import *Java 中的importmodule.*Python 中的importmoduleJava 中的importmodule

>>> import types
>>> types.FunctionType             1
<type 'function'>
>>> FunctionType                   2
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
NameError: There is no variable named 'FunctionType'
>>> from types import FunctionType 3
>>> FunctionType                   4
<type 'function'>
1types 模块不包含方法,只是表示每种 Python 对象类型的属性。注意这个属性必需用模块名 types 进行限定。
2FunctionType 本身没有被定义在当前名字空间中;它只存在于types 的上下文环境中。
3这个语法从 types 模块中直接将 FunctionType 属性导入到局部名字空间中。
4现在 FunctionType 可以直接使用,与 types 无关了。

什么时候你应该使用 from module import

  • 如果你要经常访问模块的属性和方法,且不想一遍又一遍地敲入模块名,使用 from module import
  • 如果你想要有选择地导入某些属性和方法,而不想要其它的,使用 from module import
  • 如果模块包含的属性和方法与你的某个模块同名,你必须使用 import module 来避免名字冲突。

class FileInfo(UserDict):
    "store file metadata"              1
    def __init__(self, filename=None): 2 3 4
1类也可以 (并且应该) 有doc strings ,就像方法和函数一样。
2__init__ 在类的实例创建后被立即调用。它可能会引诱你称之为类的构造函数,但这种说法并不正确。说它引诱,是因为它看上去像 (按照习惯,__init__ 是类中第一个定义的方法),行为也像 (在一个新创建的类实例中,它是首先被执行的代码),并且叫起来也像 (“init”当然意味着构造的本性)。说它不正确,是因为对象在调用__init__ 时已经被构造出来了,你已经有了一个对类的新实例的有效引用。但 __init__ 是在 Python 中你可以得到的最接近构造函数的东西,并且它也扮演着非常相似的角色。
3每个类方法的第一个参数,包括 __init__,都是指向类的当前实例的引用。按照习惯这个参数总是被称为self。在__init__ 方法中,self 指向新创建的对象;在其它的类方法中,它指向方法被调用的类实例。尽管当定义方法时你需要明确指定self,但在调用方法时,你 用指定它,Python 会替你自动加上的。
4__init__ 方法可以接受任意数目的参数,就像函数一样,参数可以用缺省值定义,即可以设置成对于调用者可选。在本例中,filename 有一个缺省值None,即Python 的空值。
注意
习惯上,任何 Python 类方法的第一个参数 (对当前实例的引用) 都叫做 self。这个参数扮演着 C++Java 中的保留字this 的角色,但selfPython 中并不是一个保留字,它只是一个命名习惯。虽然如此,也请除了self 之外不要使用其它的名字,这是一个非常坚固的习惯。
类名通常是第一个字母大写;

类中的所有东西都要缩近,就像位于函数、if 语句,for 循环,诸如此类的代码。第一条不缩近的东西不属于这个类;

Python 中,类的基类只是简单地列在类名后面的小括号里。所以 FileInfo 类是从 UserDict 类 (它是从 UserDict 模块导进来的) 继承来的。UserDict 是一个像字典一样工作的类,它允许你完全子类化字典数据类型,同时增加你自已的行为。{也存在相似的类UserListUserString ,它们允许你子类化列表和字符串。)


class FileInfo(UserDict):
    "store file metadata"
    def __init__(self, filename=None):
        UserDict.__init__(self)        1
        self["name"] = filename        2
                                       3
1一些伪面向对象语言,像 Powerbuilder 有一种“扩展”构造函数和其它事件的概念,即父类的方法在子类的方法执行前被自动调用。Python 不是这样,你必须显示地调用在父类中的合适方法。
2这个类像字典一样工作,那么这里就是第一个印象。我们将参数 filename 赋值给对象name 关键字,作为它的值。
3注意 __init__ 方法从不返回一个值。

>>> class C:
	def __init__(self,val):self.val = val
	def f(self): print "hello, my value is:", self.val

	
>>> a = C(27)
>>> b = C(42)
>>> a.f()
hello, my value is: 27
>>> b.f()
hello, my value is: 42
>>> C.f(a)
hello, my value is: 27
>>> C.f(b)
hello, my value is: 42

从上例可以看出既可以通过python自动补充参数进行实例引用,也可以通过对象将值传递;

当定义你自已的类方法时,你必须 明确将 self 作为每个方法的第一个参数列出,包括 __init__。当从你的类中调用一个父类的一个方法时,你必须包括self 参数。但当你从类的外部调用你的类方法时,你不必对self 参数指定任何值;你完全将其忽略,而Python 会自动地替你增加实例的引用。

http://www.freenetpages.co.uk/hp/alan.gauld/tutclass.htm




posted on 2022-07-05 18:13  我在全球村  阅读(31)  评论(0编辑  收藏  举报