随笔-204  评论-149  文章-0  trackbacks-0

发现很多公司要求掌握一门脚本语言,一直也想搞搞这个,看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)[1in 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 阅读(4188) 评论(0)  编辑  收藏 所属分类: Python学习

只有注册用户登录后才能发表评论。


网站导航: