发现很多公司要求掌握一门脚本语言,一直也想搞搞这个,看C++,Linux C编程也只是为了对系统更加的了解,唉,我的工作定位好像一直都不怎么明确,是要搞个自己最擅长的了,以后有时间再搞linuxC,找工作第一位。。。工作基本定位在 Java+python,大部分公司也不会要求一个人既做Java也做C++。再说这语言也是大同小异,关键还是编程思想
d = {"server":"mpilgrim", "database":"master"}
li = ["a", "b", "mpilgrim", "z", "example"]
Tuple 是不可变的 list。一旦创建了一个 tuple,就不能以任何方式改变它
t = ("a", "b", "mpilgrim", "z", "example")
连接 list 与分割字符串
>>> li = ['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
>>> s = ";".join(li)
>>> s
'server=mpilgrim;uid=sa;database=master;pwd=secret'
>>> s.split(";")
['server=mpilgrim', 'uid=sa', 'database=master', 'pwd=secret']
>>> s.split(";", 1)
['server=mpilgrim', 'uid=sa;database=master;pwd=secret']
使用 type、str、dir 和其它内置函数
4.3.2. str 函数
str 将数据强制转换为字符串。每种数据类型都可以强制转换为字符串。
例 4.6. str 介绍
>>> str(1)
'1'
>>> horsemen = ['war', 'pestilence', 'famine']
>>> horsemen
['war', 'pestilence', 'famine']
>>> horsemen.append('Powerbuilder')
>>> str(horsemen)
"['war', 'pestilence', 'famine', 'Powerbuilder']"
>>> str(odbchelper)
"<module 'odbchelper' from 'c:\\docbook\\dip\\py\\odbchelper.py'>"
>>> str(None)
'None' 对于简单的数据类型比如整型,你可以预料到 str 的正常工作,因为几乎每种语言都有一个
将整型转化为字符串的函数。
然而 str 可以作用于任何数据类型的任何对象。这里它作用于一个零碎构建的列表。
str 还允许作用于模块。注意模块的字符串形式表示包含了模块在磁盘上的路径名,所以你的显示
结果将会有所不同。
str 的一个细小但重要的行为是它可以作用于 None,None 是 Python 的 null 值。这个调用返回字符
串 'None'。你将会使用这一点来改进你的 info 函数,这一点你很快就会看到。
dir 函数返回任意对象的属性和方法列表,包括模块对象、函数对象、字符串对象、列表对象、字
典对象 …… 相当多的东西。
例 4.7. dir 介绍
>>> li = []
>>> dir(li)
['append', 'count', 'extend', 'index', 'insert',
'pop', 'remove', 'reverse', 'sort']
>>> d = {}
>>> dir(d)
['clear', 'copy', 'get', 'has_key', 'items', 'keys', 'setdefault', 'update', 'values']
>>> import odbchelper
>>> dir(odbchelper)
['__builtins__', '__doc__', '__file__', '__name__', 'buildConnectionString']
最后是 callable 函数,它接收任何对象作为参数,如果参数对象是可调用的,返回 True;否则返回
False。可调用对象包括函数、类方法,甚至类自身 (下一章将更多的关注类)。
例 4.8. callable 介绍
>>> import string
>>> string.punctuation
'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
>>> string.join
<function join at 00C55A7C>
>>> callable(string.punctuation)
False
>>> callable(string.join)
True
你已经知道 Python 函数是对象。你不知道的是,使用 getattr 函数,可以得到一个直到运行时才知
道名称的函数的引用。
例 4.10. getattr 介绍
>>> li = ["Larry", "Curly"]
>>> li.pop
<built-in method pop of list object at 010DF884>
>>> getattr(li, "pop")
<built-in method pop of list object at 010DF884>
>>> getattr(li, "append")("Moe")
>>> li
["Larry", "Curly", "Moe"]
>>> getattr({}, "clear")
<built-in method clear of dictionary object at 00F113D4>
>>> getattr((), "pop")
Traceback (innermost last):
File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'pop'
4.4.1. 用于模块的 getattr
getattr 不仅仅适用于内置数据类型,也可作用于模块。
例 4.11. apihelper.py 中的 getattr 函数
>>> import odbchelper
>>> odbchelper.buildConnectionString
<function buildConnectionString at 00D18DD4>
>>> getattr(odbchelper, "buildConnectionString")
<function buildConnectionString at 00D18DD4>
>>> object = odbchelper
>>> method = "buildConnectionString"
>>> getattr(object, method)
<function buildConnectionString at 00D18DD4>
>>> type(getattr(object, method))
<type 'function'>
>>> import types
>>> type(getattr(object, method)) == types.FunctionType
True
>>> callable(getattr(object, method))
True
使用 getattr,你能够获得同一函数的同一引用。通常,getattr(object, "attribute") 等价于
object.attribute。如果 object 是一个模块的话,那么 attribute 可能是定义在模块中的任何东西:函数
、类或者全局变量。
就是相当于函数的指针
例 4.12. 使用getattr 创建分发者
import statsout
def output(data, format="text"):
output_function = getattr(statsout, "output_%s" % format)
return output_function(data)
output 函数接收一个必备参数 data,和一个可选参数 format。如果没有指定 format 参数,其缺省
值是 text 并完成普通文本输出函数的调用。
你可以连接 format 参数值和 "output_" 来创建一个函数名称作为参数值,然后从 statsout 模块中取
得该函数。这种方式允许今后很容易地扩展程序以支持其它的输出格式,而且无需修改分发函数。
所要做的仅仅是向 statsout 中添加一个函数,比如 output_pdf,之后只要将 “pdf” 作为 format 的参
数值传递给 output 函数即可。
现在你可以简单地调用输出函数,就像调用其它函数一样。output_function 变量是指向 statsout 模
块中相应函数的引用。
你是否发现前面示例的一个 Bug?即字符串和函数之间的松耦合,而且没有错误检查。如果用户传
入一个格式参数,但是在 statsout 中没有定义相应的格式输出函数,会发生什么呢?还好,getattr
会返回 None,它会取代一个有效函数并被赋值给 output_function,然后下一行调用函数的语句将会
失败并抛出一个异常。这种方式不好。
值得庆幸的是,getattr 能够使用可选的第三个参数,一个缺省返回值。
[mapping-expression for element in source-list if filter-expression]
>>> li = ["a", "mpilgrim", "foo", "b", "c", "b", "d", "d"]
>>> [elem for elem in li if len(elem) > 1]
['mpilgrim', 'foo']
>>> [elem for elem in li if elem != "b"]
['a', 'mpilgrim', 'foo', 'c', 'd', 'd']
>>> [elem for elem in li if li.count(elem) == 1]
['a', 'mpilgrim', 'foo', 'c']
使用 and 时,在布尔环境中从左到右演算表达式的值。0、''、[]、()、{}、None 在布尔环境中为假;
其它任何东西都为真。还好,几乎是所有东西。默认情况下,布尔环境中的类实例为真,但是你可
以在类中定义特定的方法使得类实例的演算值为假。
4.6.1. 使用 and-or 技巧
例 4.17. and-or 技巧介绍
>>> a = "first"
>>> b = "second"
>>> 1 and a or b
'first'
>>> 0 and a or b
'second'
这个语法看起来类似于 C 语言中的 bool ? a : b 表达式。整个表达式从左到右进行演算,所以先进
行 and 表达式的演算。1 and 'first' 演算值为 'first',然后 'first' or 'second' 的演算值为 'first'。
0 and 'first' 演算值为 False,然后 0 or 'second' 演算值为 'second'。
然而,由于这种 Python 表达式单单只是进行布尔逻辑运算,并不是语言的特定构成,这是 and-or
技巧和 C 语言中的 bool ? a : b 语法非常重要的不同。如果 a 为假,表达式就不会按你期望的那样
工作了。(你能知道我被这个问题折腾过吗?不止一次?)
Python 支持一种有趣的语法,它允许你快速定义单行的最小函数。这些叫做 lambda 的函数,是从
Lisp 借用来的,可以用在任何需要函数的地方。
例 4.20. lambda 函数介绍
>>> def f(x):
... return x*2
...
>>> f(3)
6
>>> g = lambda x: x*2
>>> g(3)
6
>>> (lambda x: x*2)(3)
6
总的来说,lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值。lambda
函数不能包含命令,包含的表达式不能超过一个。不要试图向 lambda 函数中塞入太多的东西;如
果你需要更复杂的东西,应该定义一个普通函数,然后想让它多长就多长。
例 4.25. 打印列表
>>> li = ['a', 'b', 'c']
>>> print "\n".join(li)
a
b
c 在你处理列表时,这确实是一个有用的调试技巧。在 Python 中,你会十分频繁地操作列表。
在 2.2.1 版本之前,Python 没有单独的布尔数据类型。为了弥补这个缺陷,Python 在布尔环境 (如 if
语句) 中几乎接受所有东西,遵循下面的规则:
0 为 false; 其它所有数值皆为 true。
空串 ("") 为 false; 其它所有字符串皆为 true。
空 list ([]) 为 false; 其它所有 list 皆为 true。
空 tuple (()) 为 false; 其它所有 tuple 皆为 true。
空 dictionary ({}) 为 false; 其它所有 dictionary 皆为 true。
下面是 from module import 的基本语法:
from UserDict import UserDict
它与你所熟知的 import module 语法很相似,但是有一个重要的区别:UserDict 被直接导入到局部
名字空间去了,所以它可以直接使用,而不需要加上模块名的限定。你可以导入独立的项或使用
from module import * 来导入所有东西。
Python 中的 from module import * 像 Java 中的 import module.* ;Python 中的 import module 像 Java
中的 import module
什么时候你应该使用 from module import?
如果你要经常访问模块的属性和方法,且不想一遍又一遍地敲入模块名,使用 from module import
。
如果你想要有选择地导入某些属性和方法,而不想要其它的,使用 from module import。
如果模块包含的属性和方法与你的某个模块同名,你必须使用 import module 来避免名字冲突。
尽量少用 from module import * ,因为判定一个特殊的函数或属性是从哪来的有些困难,并且会造
成调试和重构都更困难。
from UserDict import UserDict
class FileInfo(UserDict):
在 Python 中,类的基类只是简单地列在类名后面的小括号里。不像在 Java 中有一个特殊的
extends 关键字。
Python 支持多重继承。在类名后面的小括号中,你可以列出许多你想要的类名,以逗号分隔。
class FileInfo(UserDict):
"store file metadata"
def __init__(self, filename=None):
UserDict.__init__(self)
self["name"] = filename
一些伪面向对象语言,像 Powerbuilder 有一种“扩展”构造函数和其它事件的
概念,即父类的方法在子类的方法执行前被自动调用。Python 不是这样,你必须显示地调用在父类中的合适方法。
我告诉过你,这个类像字典一样工作,那么这里就是第一个印象。我们将参数 filename 赋值给对象 name 关键字,作为它的值。 注意 __init__ 方法从不返回一个值。
Java中是自动调用默认的无参的父类的构造函数
例 5.9. 定义 UserDict 类
class UserDict:
def __init__(self, dict=None):
self.data = {} ×××××××××××××××××××××××××××××××××××定义类的实例变量
if dict is not None: self.update(dict)
注意 UserDict 是一个基类,不是从任何其他类继承而来。
这就是我们在 FileInfo 类中进行了覆盖的 __init__ 方法。注意这个父类的参数列表与子类不同。很
好,每个子类可以拥有自已的参数集,只要使用正确的参数调用父类就可以了。这里父类有一个定
义初始值的方法 (通过在 dict 参数中传入一个字典),这一方法我们的 FileInfo 没有用上。
××××××××××××××××××××××××××××××××与Java的不同×××××××××××××××××××××××××××××××××××
与Java的不同,
1,Python中类的类属性是是在类的后面直接定义的
2,而实例变量是在在__init__方法中直接定义的使用如下方式self.instancevariable=***定义,
3,然后Python中实例方法都要显示的加上self(相当于Java的this)参数,方法中引用实例变量时也要通过self来引用
Python 支持数据属性 (在 Java 叫做 “实例变量”,在 C++ 中叫 “数据成员”),它是由某个特定的类实
例所拥有的数据。在本例中,每个 UserDict 实例将拥有一个 data 数据属性。要从类外的代码引用
这个属性,需要用实例的名字限定它,instance.data,限定的方法与你用模块的名字来限定函数一
样。要在类的内部引用一个数据属性,我们使用 self 作为限定符。习惯上,所有的数据属性都在
__init__ 方法中初始化为有意义的值。然而,这并不是必须的,因为数据属性,像局部变量一样,
当你首次赋给它值的时候突然产生。
×××××××××××××××××××××××××××××××××与Java的不同××××××××××××××××××××××××××××××××××
Java 支持通过参数列表的重载,也就是 一个类可以有同名的多个方法,但这些方法或者是参数个
数不同,或者是参数的类型不同。
Python 两种都不支持,总之是没有任何形式的函数重载。一个 __init__ 方法就是一个 __init__ 方法
,不管它有什么样的参数。每个类只能有一个 __init__ 方法,并且如果一个子类拥有一个 __init__
方法,它总是 覆盖父类的 __init__ 方法,甚至子类可以用不同的参数列表来定义它。
想想为什么不支持方法重载,是因为Python的参数可以定义默认实参,有缺省值
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
应该总是在 __init__ 方法中给一个实例的所有数据属性赋予一个初始值。这样做将会节省你在后面
调试的时间,不必为捕捉因使用未初始化 (也就是不存在) 的属性而导致的 AttributeError 异常费时费
力。
class MP3FileInfo(FileInfo):
mp3file.__class__ is fileinfo.MP3FileInfo true
mp3file.__class__ is fileinfo.FileInfo false
isinstance(mp3file,fileinfo.MP3FileInfo) true
isinstance(mp3file,fileinfo.FileInfo) true
li=[1,2,3]
li2[1,2,3]
li==li2 true 相当于Java的equals()
li is li2 false 相当于Java的==
5.7. 高级专用类方法
除了 __getitem__ 和 __setitem__ 之外 Python 还有更多的专用函数。某些可以让你模拟出你甚至可
能不知道的功能。
下面的例子将展示 UserDict 一些其他专用方法。
例 5.16. UserDict 中更多的专用方法
def __repr__(self): return repr(self.data)
def __cmp__(self, dict):
if isinstance(dict, UserDict):
return cmp(self.data, dict.data)
else:
return cmp(self.data, dict)
def __len__(self): return len(self.data)
def __delitem__(self, key): del self.data[key] __repr__ 是一个专用的方法,在当调用 repr
(instance) 时被调用。repr 函数是一个内置函数,它返回一个对象的字符串表示。它可以用在任何
对象上,不仅仅是类的实例。你已经对 repr 相当熟悉了,尽管你不知道它。在交互式窗口中,当你
只敲入一个变量名,接着按ENTER,Python 使用 repr 来显示变量的值。自已用一些数据来创建一
个字典 d ,然后用 print repr(d) 来看一看吧。
__cmp__ 在比较类实例时被调用。通常,你可以通过使用 == 比较任意两个 Python 对象,不只是
类实例。有一些规则,定义了何时内置数据类型被认为是相等的,例如,字典在有着全部相同的关
键字和值时是相等的。对于类实例,你可以定义 __cmp__ 方法,自已编写比较逻辑,然后你可以
使用 == 来比较你的类,Python 将会替你调用你的 __cmp__ 专用方法。
__len__ 在调用 len(instance) 时被调用。len 是一个内置函数,可以返回一个对象的长度。它可以
用于任何被认为理应有长度的对象。字符串的 len 是它的字符个数;字典的 len 是它的关键字的个
数;列表或序列的 len 是元素的个数。对于类实例,定义 __len__ 方法,接着自已编写长度的计算
,然后调用 len(instance),Python 将替你调用你的 __len__ 专用方法。
__delitem__ 在调用 del instance[key] 时调用 ,你可能记得它作为从字典中删除单个元素的方法。
当你在类实例中使用 del 时,Python 替你调用 __delitem__ 专用方法。
在 Java 中,通过使用 str1 == str2 可以确定两个字符串变量是否指向同一块物理内存位置。这叫做
对象同一性,在 Python 中写为 str1 is str2。在 Java 中要比较两个字符串值,你要使用 str1.equals
(str2);在 Python 中,你要使用 str1 == str2。某些 Java 程序员,他们已经被教授得认为,正是因为
在 Java 中 == 是通过同一性而不是值进行比较,所以世界才会更美好。这些人要接受 Python 的这
个“严重缺失”可能要花些时间。
ord("a") 97
ord("A") 65
5.8. 类属性介绍
你已经知道了数据属性,它们是被一个特定的类实例所拥有的变量。Python 也支持类属性,它们是
由类本身所拥有的。
例 5.17. 类属性介绍
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)}
例 5.18. 修改类属性,Java中的静态变量
>>> class counter:
... count = 0
... def __init__(self):
... self.__class__.count += 1 #一定得用self.__class__来引用,才是类变量,假如用self.count则定义的是实例变量,或者用
Counter.count +=1
...
上述代码记录创建的对象的个数
5.9. 私有函数
与大多数语言一样,Python 也有私有的概念:
私有函数不可以从它们的模块外面被调用
私有类方法不能够从它们的类外面被调用
私有属性不能够从它们的类外面被访问
与大多数的语言不同,一个 Python 函数,方法,或属性是私有还是公有,完全取决于它的名字。
如果一个 Python 函数,类方法,或属性的名字以两个下划线开始 (但不是结束),它是私有的;其它
所有的都是公有的。 Python 没有类方法保护 的概念 (只能用于它们自已的类和子类中)。类方法或
者是私有 (只能在它们自已的类中使用) 或者是公有 (任何地方都可使用)。
在 MP3FileInfo 中,有两个方法:__parse 和 __setitem__。正如我们已经讨论过的,__setitem__
是一个专有方法;通常,你不直接调用它,而是通过在一个类上使用字典语法来调用,但它是公有
的,并且如果有一个真正好的理由,你可以直接调用它 (甚至从 fileinfo 模块的外面)。然而,
__parse 是私有的,因为在它的名字前面有两个下划线。
在 Python 中,所有的专用方法 (像 __setitem__) 和内置属性 (像 __doc__) 遵守一个标准的命名习惯
:开始和结束都有两个下划线。不要对你自已的方法和属性用这种方法命名;到最后,它只会把你 (或其它人) 搞乱。
#!/usr/bin/env python
#coding=utf-8
import os
import sys
from UserDict import UserDict
def stripnulls(data):
"strip whitespace and null"
return data.replace("\00","").strip()
class FileInfo(UserDict):
"store file metadata"
def __init__(self,filename=None):
UserDict.__init__(self)
#will trigger the __setitem__ method,and this method be override in the sub class
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 object for files of particular"
fileList = [os.path.normcase(f)
for f in os.listdir(directory)]
fileList = [os.path.join(directory,f)
for f in fileList if os.path.splitext(f)[1] in fileExtList]
def getFileInfoClass(filename,module=sys.modules[FileInfo.__module__]):
"get file into class from filename extension"
subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:]
return hasattr(module,subclass) and getattr(module,subclass) or FileInfo
return [getFileInfoClass(f)(f) for f in fileList]
if __name__=="__main__":
for info in listDirectory("G:\\test",[".mp3"]):
print "\n".join(["%s=%s" % (k,v) for (k,v) in info.items()])
print
posted on 2009-08-22 00:02
Frank_Fang 阅读(4195)
评论(0) 编辑 收藏 所属分类:
Python学习