2005年01月31日

这几天要用python写个小程序,其中需要发送中文邮件。经过一番尝试,成功。把一点心得写下来。
  宗旨:支持中文,支持附件,不用第三方模块。

不含附件的文本邮件

  

#coding=cp936

from email.MIMEText import MIMEText
from email.Header import Header
import smtplib

msg=MIMEText(‘hello world! 中文邮件测试’,_subtype=’plain’,_charset=’gb2312′)
msg['subject']=Header(‘中文邮件名测试test!’,‘gb2312’)
msg['from']=’test@yahoo.com’ #邮件client的所显示的sender,可有也可以
msg['to']=’hello@yahoo.com’ #邮件client 所显示的收件人。显示什么可以自己定

fromaddr=’test@yahoo.com’
toaddrs=['hell01@yahoo.com','hello2@yahoo.com']

server.smtp(’smtp.mail.yahoo.com.cn’)  #通过yahoo的免费邮箱发送。
server.login(‘loginname’,'password’)  #yahoo smtp需要认证
server.sendmail(fromaddr,toaddrs,msg.as_string())


邮件正文为html


 只需对上面做一点改动
msg=MIMEText(‘hello world! 中文邮件测试’,_subtype=’plain’,_charset=’gb2312′)
改为
txt=’<html><body>hello world! 中文邮件测试</body></html>’
msg=MIMEText(txt,_subtype=’html’,_charset=’gb2312′)



邮件带附件

 #coding=cp936
from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart

from email.Header import Header
import smtplib, base64, sys

msg=MIMEMultipart()  #支持附件
txt1=MIMEText(‘邮件正文’,_subtype=’plain’,_charset=’gb2312′)
txt1.replace_header(‘Content-Transfer-Encoding’, ‘quoted-printable’)  #否则邮件原文看不懂,但并不影响读信
msg.attach(txt1)

txt2=base64.encodestring(open(‘中文附件名test.rar’,'rb’).read()  #附件base64编码
txt2=MIMEText(txt2)
txt2.replace_header(‘Content-Type’, ‘application/octet-stream; name=”%s”‘ % Header(‘中文f附件名测试test.rar’,'gb2312′))
txt2.add_header(‘Content-Disposition’, ‘attachment;filename=”%s”‘ %Header(‘中文附件名测试test.rar’,'gb2312′) )
msg(attach.txt2)

msg['subject']=Header(‘中文邮件名测试test!(含附件)’,‘gb2312’)

msg['from']=’test@yahoo.com’

msg['to']=’hello@yahoo.com’



fromaddr=’test@yahoo.com’

toaddrs=['hell01@yahoo.com','hello2@yahoo.com']



server.smtp(’smtp.mail.yahoo.com.cn’) 

server.login(‘loginname’,'password’)

server.sendmail(fromaddr,toaddrs,msg.as_string())


2005年01月28日

学习资料来自于ring翻译的python cook book.源贴于linuxforum ,此处只是记录我自己的一点理解

次处理字符串中一个字符

Python中字符就是长度为1的字符串

1: L=list(string)

2: 直接当成列表用

  for c in string:

3: map(function,string)

unicode串一样可以被正确处理。如

s=unicode(‘中文测试test’,’cp936’)

for c in s:

   print c

 

判断一个对象是否StringLike

在乱记3里面的评论我写了自己最初在这个问题上的理解错误。

def StringLike( obj ):

    try:

      obj + ‘’

    except: return 0

    else: return 1

上面这个是通用的解决方法,适用于所有具有字符串特性的各种对象。

 

排列字符串

ljust rjust center

print ‘|’,’hej’.ljust(20),’|’,’hej’.rjust(20),’|’,’hej’.center(20)

每本python书的前面好像都介绍过。不过真到使用的时候还不一定想得起来。CookBook中特别在最后把一些字符串的基本操作再介绍一遍也是这个道理吧。

 

从尾部清除空格

lstrip rstrip strip

这里的空格包括(blank, tabs, newlines )

很有趣,支持全角中文空格。

 

合并字符串

方法不少,最高效的还是join。所以如果确实有很多小字符串要连接的话,最好还是放到一个列表中去。python中每个字符串都是不可变的,任何对字符串的改动,python都要重新建立新的字符串。

s1+s2+s3

largestring=”%s%s%s”
% (s1,s2,s3)

largestring=reduce(operator.add,pieces)

largestring=’’.join(pieces)
#
最高效的方式


  还是要感谢ring 以及其他的朋友将这个好东西翻译、组织起来,给我们这些初学者提供了一个很好的level up的东东,对于python也有了更进一步的了解。
  我的感觉是,越学越喜欢,同时越学也愈发被python的强大所震惊。
  python……有点意思:)



学习资料来自于ring翻译的python cook book.源贴于linuxforum ,此处只是记录我自己的一点理解


行代码完成的QuickSort

很漂亮,但不很实用。

 

def qsort(L):
     if len(L) <= 1: return L
     return qsort([lt for lt in L[1:] if lt < L[0]]) + L[0:1] + \
            qsort([ge for ge in L[1:] if ge >= L[0]])

 

不仅速度上没有标准的列表sort快,最重要的是由于采用了递归调用,当列表大一时就会超出python的递归深度的最大限度。我测试列表长度只能到900多。不过用来展现列表包容的优雅和简练还是相当不错的。

Ps:算法没看懂。 :(




使用sqlorder by 语法来为对象排序

十分有趣的解法。为每组数据逐一将创建sqlSortable对象并放入其中,通过重载__cmp__来重定义cmp比较的结果。

testList =
[sqlSortable(program=program, name=name) for program, name in data]

前面的关键字在替换时{‘program’=program,’name’=name}所以前面的不会被替换掉。

class sqlSortable:
 
     def __init__(self, **args):
         self.__dict__.update(args)
 
     def setSort(self, sortOrder):
         self.sortFields = []
         for text in sortOrder:
             sortBy, direction = (text+' ').split(' ', 1)
             self.sortFields.append((sortBy, direction[0:4].lower(  ) == 'desc'))
 
     def __repr__(self):
         return repr([getattr(self, x) for x, reverse in self.sortFields])
 
     def __cmp__(self, other):
         myFields    = []
         otherFields = []
         for sortBy, reverse in self.sortFields:
             myField, otherField = getattr(self, sortBy), getattr(other, sortBy)
             if reverse:
                 myField, otherField = otherField, myField
             myFields.append(myField)
             otherFields.append(otherField)
         return cmp(myFields, otherFields)
 
 def testSqlSortable(  ):
     data = [('Premier', 'Stealth U-11'), ('Premier', 'Stealth U-10'),
             ('Premier', 'Stealth U-12'),
             ('Co-ed',   'Cyclones'),     ('Co-ed',   'Lightning'),
             ('Co-ed',   'Dolphins'),
             ('Girls',   'Dynamos'),      ('Girls',   'Tigers'),
             ('Girls',   'Dolphins')]
 
     testList = [sqlSortable(program=program, name=name) 
                 for program, name in data]
     
     tests = [['program DESC', 'name'],
              ['name desc', 'program asc']]
 
     for sortBy in tests:
         print '#### Test basic sorting ###', sortBy
         for sortable in testList:
             sortable.setSort(sortBy)
         testList.sort(  )
         for item in testList:
             print item
 
     print '#### Test modification of attributes ###', sortBy
     assert testList[4].name == 'Lightning'
     testList[4].name = 'ZZ 1st name'
     testList.sort(  )
     for item in testList:
         print item
 
 if __name__ == '__main__':
     testSqlSortable(  )

 

 

2005年01月27日

 学习资料来自于ring翻译的python cook book.源贴于linuxforum ,此处只是记录我自己的一点理解

在一个序列上执行频繁的成员关系测试

判段列表中是否包含某元素。

这个程序主要应用了字典索引以及动态重载。其中动态重载尤其有趣,通过动态重载减轻了大量的代码编写时间,将list中有可能导致内容变化的方法外全部包上了一个状态复位的标志设定。

#coding=cp936
 class FunkyList(list):
     def __init__(self,initlist=None):
         if initlist==None:
             list.__init__(self)
         else:
             list.__init__(self,initlist)
         self._dict_ok=0
 
     def __contains__(self,item):
         if not self._dict_ok:
             self._dict=dict(zip(self,self))
             self._dict_ok=1
         return item in self._dict
 
 def _wrapMethod(methname):
     _method = getattr(list, methname)
     def wrapper(self, *args):
         self._dict_ok=0  #对所有会造成list改动的方法外面包上_dict_ok=0
         return _method(self, *args) 
     setattr(FunkyList, methname, wrapper)
 
 for meth in 'setitem delitem setslice delslice iadd'.split():
     _wrapMethod( '__%s__'% meth )
 
 for meth in 'append insert pop remove extend'.split():
     _wrapMethod( meth )
 
 del _wrapMethod

 

 

在一个嵌入的序列中发现一个条目的深度搜索

程序利用递归调用返回包含元素的位置。其中最有趣的是对异常的利用。

#coding=cp936
 import sys
 class Found(Exception): pass #exception做条件判断,有意思
 
 _indices = xrange(sys.maxint)
 
 def _is_sequence(obj):
     return isinstance(obj, list) or isinstance(obj, tuple)
 
 def deepindex(sequence, goal, is_subsequence=_is_sequence):
     """ deepindex(sequence, goal) -> index list """
     def helper(sequence, index_list, goal=goal):
         for item, index in zip(sequence, _indices):
             if item==goal:
                 raise Found, index_list+[index] #利用exception返回值
             elif is_subsequence(item):
                 helper(item, index_list+[index])
     try: helper(sequence, [])
     except Found, index_list: return index_list
     else: return -1
 
 if __name__=='__main__':
     print deepindex([[1,2],[3,[4,[5,6]]],7,[8,9]], 6)
     print deepindex([[1,2],[3,[4,[5,6]]],7,[8,9]], 66)

  这个配方尽管是有争议的,但对于把引发一个异常作为一种途径从深度的嵌套递归调用中返回
值的概念来说,它是有趣的,可以炫耀的。如果为可选择的控制结构来使用
异常作为一个构建的块
是合适的。这个案例对他们的应用来说的确是。我们避免了不
得不安排一些人工的“找到”对“没找到”
的引号方法,并且,更好的是,我们避免了不
得不为当一个条目被发现的时候,从一个深度调用堆栈
返回的复杂性。在任何情况下,
在python里,这个用法的确强调对于不是错误的条件,异常怎样能
被使用,并且甚
至不是一个真正的异常。
  


学习资料来自于ring翻译的python cook book.源贴于linuxforum ,此处只是记录我自己的一点理解

用二分法在list中搜索

二分法是bisect 提供的基本算法

thislist.sort()
#
必须先排序,否则无法进行二分法搜索

item_insert_point
= bisect.bisect (thislist, theitem )

is_present =
thislist[item_insert_point-1:item_insert_point]==[theitem]

#通过使用slice可以保证在即使没有搜索结果的情况下仍能返回[],这样就不用try

二分法搜索在数据集巨大的情况下效果非常明显,不过最初的sort会有一定的消耗,如果不是频繁查找,个人感觉index就够用了。

 

通过对象属性来排序对象列表

通常的做法:

classlist.sort(lambda
x,y : (cmp(getattr(x,attr),getattr(y,attr))))

快一点的方法:

建立辅助索引

import
operator

tempclasslist
= map ( None , map(getattr,classlist,attr),xrange(len(classlist)),classlist)

tempclasslist.sort()

classlist =
map (operator.getitem,tempclasslist,[-1]*len(classlist))

 

通过元素或者属性来排序

 #coding=cp936
 class Sorter(object):
     def _helper(self,data,aux,inplace):
         aux.sort()
         result=[data[i] for junk, i in aux]
         if inplace:
             data[:]=result
         return result
 
     def byItem(self, data, itemindex=None, inplace=1): 
         if itemindex is None:
             if inplace:
                 data.sort()
                 result = data #直接对源数据sort
             else:
                 result = data[:]
                 result.sort()
                 return result #inplace!=1 赋值
         else:
             aux=[(data[i][itemindex],i) for i in range(len(data))] #[属性,索引]
             return self._helper(data,aux,inplace)
 
     sort=byItem
     __call__=byItem  # sort(data)
 
     def byAttribute(self, data, attributename, inplace=1):
         aux=[(getattr(d[i],attributename),i) for i in 
range(len(data))]
         return self._helper(data,aux,inplace)
 
 
 
 sort = Sorter()
 
 list=[(1,2),(4,8),(0,3)]
 dict=[{'a':3,'b':4},{'a': 5, 'b': 2}, {'a': 0, 'b': 0},{'a': 9, 'b': 9}]
 dumb = [1, 4, 6, 7, 2, 5, 9, 2, 4, 6]

 

通过inplace来确定是否返回值还是在源值修改

__call__ 可实现如下功能:

sort = Sorter()

sort(list)

 

def byAttribute 在本例中没有使用。。疑惑中

 

不用循环从list中随机取值

直接使用random中提供的方法

Import random

random.shuffle(list)   #life is random  J  ipod shuffle ?

for item in
list:

    process (item)

 

random.shuffle的实现十分高效基本原理是

随机进行 x[i], x[j] = x[j], x[i] 数据位置调换,如此不用建立任何新的数据集开销小,速度快

 


2005年01月26日

学习资料来自于ring翻译的python cook book.源贴于linuxforum ,此处只是记录我自己的一点理解

有效处理选择结构数据对

处理有配对的大数据集。

方法:使用一个辅助的字典作数据预处理
可以把O(M*N) 变成 O(M+N)

例子:有两个日志 weblog (网站日志) clog (信用卡支付日志) 其中ipaddress为配对条件

weblog=[[‘202.11.23.43’,’/main’,’2005-1-1
1:23
’,23] ……….]

clog=[[‘202.11.23.43’,30,’2005-2-3
12:23’,’Visa’]
……. ]

O(M*N)解决方法

result=[process(webhit,ccinfo)
for webhit in weblog for ccinfo in clog

 if 
webhit[0]==ccinfo[0]]

O(M+N)

ipdict={}

for webhit in
weblog:

   
ipdict.setdefault(webhit[0],[]).append(webhit)

#ipdict {‘202.11.23.43’:[[ ‘202.11.23.43’,’/main’,’2005-1-1
1:23
’,23],[….]],…}

result=[precess(webhit,ccinfo)
for ccinfo in clog for webhit in ipdict[ccinfo[0]]]

 

 

保持稳定性同时排序

由于Python中排序的不确定性,有时需要对值相同的记录在排序后保持排序前的顺序。

通过建立建立索引来保证排序后的顺序

def
stable_sort(alist, indices=xrange(sys.maxint)):

    temp=zip(alist,indices)

    temp.sort()

    alist[:]=[item for item,index in temp]

 

通过多个条件来排序List

方法1

通过传递一个比较函数至sort内,该种方法速度较慢,适合较小的list

import stirng

star_list=[‘Elizabeth
Taylor’, ‘Bette Davis’, ‘Hugh Grant’, ‘C. Grant’]

star_list.sort(lambda
x,y : (cmp(string.split(x)[-1], string.split(y)[-1]) or cmp(x,y)))

#sort by lastname then by first name

 

方法2

def
sorting_criterion_1(data):

    return string.split(data)[-1]  #last name

 

def
sorting_criterion_2(data)

    return len(data)  #增加一个长度条件

 

#打包

aux_list=map(lambda
x:(sorting_criterion_1(x),

                    sorting_criterion_2(x),

                    x),

                    star_list)

aux_list.sort()

#解包

star_list=[star[-1]
for star in aux_list]

 

字母反序排序

import string

all_characters =
string.maketrans(”,”)  
字母表字符串

all_characters_list =
list(all_characters)

all_characters_list.reverse( )

rev_characters =
”.join(all_characters_list)

rev_trans =
string.maketrans(all_characters, rev_characters)  

 

# Pack a better-ordered and corrected
auxiliary list:

aux_list = map(lambda x:
(string.translate(sorting_criterion_1(x), rev_trans),

sorting_criterion_2(x),

x),

star_list)

 

aux_list.sort( )

 

# Unpack the resulting list:

star_list = map(lambda x: x[-1],
aux_list)

 

 

 

2005年01月25日

学习资料来自于ring翻译的python cook book.源贴于linuxforum ,此处只是记录我自己的一点理解


通过多个list循环

a=[‘a1’,’a2’,’a3’]

b=[‘b1’,’b2’]

for x,y in
[(x,y) for x in a for y in b]:

    print x,y

更多的list也可以

For x,y,z in
[(x,y,z) for x in a for y in b for z in c]: #
以此类推

 

变换二维数组

行变列

arr=[[1,2,3],[4,5,6],[7,8,9],[10,11,12]]  #行列必须整齐

print
[[r[col] for r in arr] for col in range(len(arr[0]))]

 

 

建立非共享的多维数组

共享的多维数组

d=[[0]*3]*3

print d

[[0,0,0],[0,0,0],[0,0,0]]

d[0][0]=1

[[1,0,0],[1,0,0],[1,0,0]]

list包容建立非共享多维数组

d=[0 for col
in range(3) for row in range(3)]

 

给字典排序

1:

   def sortDict(adict):

       items=adict.items()

       items.sort()

       return [value for key,value in items]

2: speed up!

    def sortDict(adict):

       keys=adict.keys()

       keys.sort()

       return [adict[key] for key in keys]

3:speed up! Up!

     def sortDict(adict):

        keys=adict.keys()

        keys.sort()

        return map(adict.get,keys)

4:speeeeeed
up!   Ver>2.0

      Def sortDict(adict):

         keys=adict.keys()

         keys.sort()

         return map(adict.__getitem__,keys)

 

生成浮点数range

def frange(start,end=None,inc=1.0):
        if end == None:
               end = start + 0.0
               start = 0.0
        assert inc  
 
        
        i=0
        while 1:
               next = start + i*inc
               if inc>0 and next>=end:
                       break
               elif inc<0 and next <=end:
                       break
               yield next
               i+=1
 
 for i in frange(0,10,0.25):
     print i

 

# assert #断言一种检查的手段。当条件不满足时程序退出,并打印出出错的地方。多用于参数的合法性检查。


学习资料来自于ring翻译的python cook book.源贴于linuxforum ,此处只是记录我自己的一点理解

拉平一个嵌套的序列

应用迭带器和生成器

原文的例子有点问题。原文中应用iter(obj) 来判断是否能够继续loop,但是对于’a’这样即使只有一个字符的字符串iter仍然可以生成迭带,另外对于单字符也判断成isstringlike造成逻辑上的混乱,因此做了一定的改动。但感觉不是太好。

#coding=cp936
 def flatten(sequence,scalarp):
     for item in sequence:
         if scalarp(item)!=1:
             yield item
         else:
             for subitem in flatten(item,scalarp):
                 yield subitem
 
 def canLoopOver(maybeIterable):
     try:
         iter(maybeIterable)
     except:
         return 0
     else:
         return 1
 
 def isStringLike(obj):
     try:
         obj+''
     except :
         return 0
     else:
         if len(obj)==1 :return 2
         return 1
 
 def isScalar(obj):
     if isStringLike(obj)==0:
         if canLoopOver(obj)==1:
             return 1
         else:
             return 0
     elif isStringLike(obj)==2:return 0
     else:
         return 1
 
 a=[[1,2,3],2,3,'yes',4,[5,6,7,[1,2]],3,'hello',u'中文']
 f=flatten(a,scalarp=isScalar)
 b=[]
 while 1:
     try:
         b.append(f.next())
     except:
         break
 print b

 

[1, 2, 3, 2, 3, 'y', 'e', 's', 4, 5, 6,
7, 1, 2, 3, 'h', 'e', 'l', 'l', 'o', u'\u4e2d', u'\u6587']

 

在索引和序列元素上并行循环

几种方法的效率都差不太多。

indices =
xrange(sys.maxint)  #xrange
不直接创建列表 另外还可以使用xzip

seq=[‘a’,’hello’,’good’]

1:

for item, index in zip ( seq , indices ):

    something(item, index)

2:

    for index in range(len(seq)):

        somethine(seq[index],index)

3:

    class indexed:

        def __init__(self, seq):

            self.seq=seq

        def __getitem__(self,i):

            return self.seq[i], i

    i=indexed(seq)

    for item,index in i(seq):

        something(item,index)

4:

    def indexed(seq):

        iterator=iter(seq)

        for index in indices:

            yield iterator.next() , index

    for item, index in indexed(seq):

        something(item,index)

2005年01月24日

学习资料来自于ring翻译的python cook book.源贴于linuxforum ,此处只是记录我自己的一点理解

把一个键同多个值关联起来

d={}

添加: 1对多 列表  d.setdefault(‘key’,[]).append(value)

       11  字典 
d.setdefault(‘key’,{})[value]=1

删除: d[key].remove(value)  #1对多 只删除最前面的一个

       del
d[key][value]

       del
d[key][index]

获取: 1对多

       有返回列表,没有返回false

       def has_key_with_some_values( d, key):

            return d.has_key(key) and d[key]

       有返回列表,没有返回空列表。这个方法相对方便一些,因为返回类型一致

       def get_value_if_any( d, key):

            return d.get(key,[])

       11

       d[key].keys()

 

使用字典来分发Otter中曾经使用过getattr

必须先声明函数才能赋值

def do_dog(a,b):

    pass

….

f={‘dog’:do_dog,
‘cat’:do_cat, ‘bird’:do_bird}

f[‘dog’](a,b)
即可调用

也可以使用列表

F=[do_dog,do_cat,do_bird]

F[1](3,2)

 

发现两个集合的交集

d1={‘zope’:’test’,’python’:’test2’}

d2={‘python’:’test3’,’perl’:’$’}

使用filter

filter(d2.has_key,d1.keys())

使用list包含

[k for k in
d1 if k in d2]  # for k in d1
会隐式调用字典的iterkeys方法 if等价于has_key

 

Function
and a or b

条件如果成立返回a,否则返回b。可以没有or b 则返回false

3>0 and 1 or 0     1

3>4 and 1 or 0     0

3>4 and 1         false

 

用一个语句来赋值和测试

实现perl if x=foo():

通过自定义一个方法来实现。

技巧: __builtin__ 增加一个新的内建对象

import __builtin__

__builtin__.dataholder=dataholder

__builtin__.data=dataholder()

 

使用list包容代替map,filter  (ver>2.0)

l=[1,10,20,5,25]

列表中每个元素增加23

map(lambda
x:x+23 , l)

[k+23 for k
in l]

列出大于5的元素,返回列表

filter(lambda
x:x>5 , l)

[k for k in l
if k>5]

 

列出大于5的值且增加23

map(lambda
x:x+23 , filter( lambda x:x>5, l))

[k+23 for k
in l if k>5]  #
清晰,简洁。

   

   
List
包容来源于http://www.haskell.org

 

解包简单的类list对象

实际就是建立一个zip对应的unzip方法

zip([2,3,4],’hello’,(3,4,’as’))   => 
[(2,’h’,3),(3,’e’,4),(4,’l’,’as’)]

def unzip(p,
n):

    mlen, lft = divmod( len(p), n)  #技巧
divmod
直接获得商(整)及余

    if lft != 0 : mlen +=1

    lst=[[None]*mlen for I in range(n)]  #初始化,且效率高于append

    for I in range(len(p)):

        j , k = divmod( i , n )

            lst[k][j] = p[i]

       
return map(tuple, lst)    #
子序列tuple




2005年01月21日

刚才上来发点东西,猛然间发现页面最上方增加了一排link。照理说,免费服务商增加点东西也无可厚非,不过总觉得怪怪的。最上面的picture也被link拽的repeat了。但愿不要过些日子再来点漂浮图片什么的,那我可就欲哭无泪了。