《Python高级编程技巧》学习笔记

2-1列表、字典、集合筛选数据

  • filter
from random import randint
data = [randint(-10,10) for _ in xrange(10)]
filter(lambda x : x>=0,data)  
  • 推导式

在 Ipython 中使用 timeit可以进行计时
timeit filter(lambda x : x =='a',data)

2-2命名元祖

from collections import namedtuple 
p = namedtuple('Point',['x','y'])
p.x,p.y=1,2
print p.x+p.y

2-3 统计元素出现频率

from collections import Counter
from random import randint

data = [randint(0,20) for _ in xrange(20)]
c = Counter(data)
print c.most_common(1)

2-4根据字典的值排序

  • 使用 zip
  • 使用 sort
from random import randint                                                               
d = {x:randint(0,100) for x in 'xyzabc'}  
print sorted(zip(d.values(),d.keys()))
print sorted(d.items(),key=lambda x:x[1])

2-5获取字典公共键

1.使用 viewkeys 方法获得集合再取交集
2.使用 map函数获取所有字典的 key 的集合
3.使用 reduce函数依次取交集

from random import randint,sample
s1={x:randint(1,4) for x in sample('abcdefg',randint(3,6))} 
s2={x:randint(1,4) for x in sample('abcdefg',randint(3,6))} 
s3={x:randint(1,4) for x in sample('abcdefg',randint(3,6))} 
reduce(lambda a,b:a&b,map(dict.viewkeys,[s1,s2,s3])) 

2-6有序字典

from time import time
from random import randint
from collections import OrderedDict
d = OrderedDict()
players = list('ABCDEFGH')
start = time()

for i in xrange(8):
    raw_input()
    p = players.pop(randint(0,7-i))
    end = time()
    print i+1,p,end -start,
    d[p]=(i+1,end-start)
    
print

for k in d:
    print k,d[k]                            

2-7利用队列实现历史记录

from collections import deque 
q = deque([],5) 

3-1可迭代对象和迭代器对象

  • 可迭代对象能够通过iter()函数得到一个迭代器对象
  • 实现了__iter____getitem__方法的对象是可迭代对象

3-2实现可迭代对象和迭代器

  • 可迭代对象,要实现__iter__方法,该方法要返回一个迭代器。
  • 迭代器要实现一个next()函数,该函数返回一个结果,同时需要在结束时抛出StopIteraion异常
  • 可以直接把__iter__实现为一个生成器

3-4实现反向迭代

  • 实现__reversed__函数
class FloatRange:
    def __init__(self, start, end, step=0.1):
        self.start = start
        self.end = end
        self.step = step

    def __iter__(self):
        t = self.start
        while t <= self.end:
            yield t
            t += self.step

    def __reversed__(self):
        t = self.end
        while t >= self.start:
            yield t
            t -= self.step
for x in reversed(FloatRange(1.0, 4.0, 0.5)):
    print x

3-5对可迭代对象使用切片

from itertools import islice 

Docstring:
islice(iterable, [start,] stop [, step]) --> islice object

Return an iterator whose next() method returns selected values from an
iterable. If start is specified, will skip all preceding elements;
otherwise, start defaults to zero. Step defaults to one. If
specified as another value, step determines how many values are
skipped between successive calls. Works like a slice() on a list
but returns an iterator.
Type: type

这个函数使用后,会消耗掉已经生成的元素

3-6同时迭代多个可迭代对象

  • 并行:zip()
  • 串行:from itertools import chain

4-1拆分多种分隔符的字符串

  • 反复使用split函数
def mysplit(s,ds):                                                               
      res = [s]                                                                    
      for d in ds:                                                                 
          t = []                                                                   
          map(lambda x : t.extend(x.split(d)),res)                                 
          res = t                                                                  
      return res 
  • 使用re.split()函数

4-3 如何调整字符串中文本的格式

re.sub('(\d{4})-(\d{2})-(\d{2})',r'\2/\3/\1',log)  

4-4拼接多个短字符串

  • 累加
  • join()函数,接受一个可迭代的字符串对象

4-5 如何对字符串进行左, 右, 居中对齐

  • str.ljust(),str.rjust(),str.center()
s.ljust(20,'*')                                                                 
Out[13]: 'abc*****************'
  • format()配置参数>20 <20 ^20
format(s,'<20')                                                                 
Out[19]: 'abc                 ' 

4-6 如何去掉字符串中不需要的字符

  • strip(),lstrip(),rstrip()去除两端字符
  • re.sub或者replace
  • translate

S.translate(table [,deletechars]) -> string

Return a copy of the string S, where all characters occurring
in the optional argument deletechars are removed, and the
remaining characters have been mapped through the given
translation table, which must be a string of length 256 or None.
If the table argument is None, no translation is applied and
the operation simply removes the characters in deletechars.
Type: builtin_function_or_method

5 文件操作

6 解析 cvs,xml,excel,json

6.1解析 cvs

import cvs
rf = open('file.cvs','rb')
reader = cvs.reader(rf)#生成器
reader.next()

wf = open('file.cvs','r')
writer = cvs.writer(wf)#生成器
writer.next()


6.2解析 xml

7 类与对象

7-1 如何派生内置不可变类型并修改实例化行为

派生一个元组类型,只保留整型

class IntTuple(tuple):
    def __new__(cls,iterable):
        g = (x for x in iterable if isinstance(x,int))
        return super(IntTuple,cls).__new__(cls,g)
        
    def __init__(self,iterable):
        super(IntTuple,self).__init__(iterable)
        
t = IntTuple([1,-1,'abc',['x','y'],3])
print t

7-2 利用__slot__来节省对象的内存开销

当我们不使用__slot__时,类对象使用一个 dict 来对对象的属性进行动态绑定。对象的属性就是该字典中的一个元素,可以动态添加或解除。

p = Player()
p.__dict__['x']=1
>> p.x = 1

该机制需要维护一个字典,占据大量空间。

使用预定义的 __slot__ = ['x','y'],可以预定义对象的属性,不允许动态添加。

7-3 如何让对象支持上下文管理

让对象支持 with 语句,需要定义 __enter____exit__函数

def __enter__(self):
    self.tn = Telnet()
    return self
def __exit__(self):
    self.tn.close()

当发生异常时,能正确调用__exit__,如果该函数返回一个 True,则可以压制 with 语句中的异常。

7-4 如何创建可管理的对象属性

利用 getter 和 setter 来管理对象属性,但是这样做调用起来比较麻烦。可以使用@property装饰器来简化

class Student(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value

当然也可以利用property() 函数

R = property(getter,setter)
C.R = 1 #调用 getter
print C.R #调用 setter

7-5 如何让类支持比较操作

  • 实现 __lt__,__ie__,__gt__,__ge__,__eq__,__ne__
  • 装饰器 @total_ordering可以通过逻辑运算自动进行推测,我们可以只定义小于和等于两种比较运算符
  • 对于两个不同的类的对象,如果其中一个类实现了比较,那么当这个类作为比较运算符的左值时才可以正确执行,否则不等式两边的类都要实现全部相关比较操作符
  • 为了应对上述问题,我们可以定义一个抽象的公共基类
from abc import abstractmethod
class shape(object):
    @abstractmethod
    def area(self):
        pass
    def __lt__(self,obj):
        return self.area()<obj.area()

class rect(shape):
    def area(self):
        return self.x * self.y
class tri(shape):
    def area(self):
        return 0.5*self.x * self.h

7-6 如何使用描述符对实例属性做类型检查

8 多线程

8-1 如何使用多线程


from threading import Thread

class myThread(Thread):
    def __init__(self,sid):
        Thread.__init__(self)
        self.sid = sid
    def run(self):
        handle(self.sid)
 
threads = []       
for i in range(1,11):
    t = myThread(i)
    threads.append(t)
    t.start()
for t in threads:
    t.join() #必须在不同的循环中调用 join 否则会依次阻塞变成线性执行

python 中的线程只适合处理 IO 密集型操作而不是 CPU 密集型操作

8-2 如何线程间通信

定义两个线程,DownloaderCoverter前者是生产者,后者是消费者
可以通过一个全局变量来进行数据通信,但是再操作数据前要调用 lock 函数加锁。或者可以使用线程安全的数据结构,例如from Queue import Queue
通常情况下,使用全局变量是不优雅的,可以通过构造器将队列传入,并使用 self.queue来维护。

8-3 如何在线程间进行事件通知

每下载100个 xml 文件,通知压缩线程来压缩,压缩线程执行完毕后,再通知下载函数继续下载

ipython 中输入!开头的命令,可以执行 shell 命令

from threading import Event,Thread    
class CovertThread(Thread):
    def __init__(self,cEvent,tEvent):
        Thread.__init__(self)
        self.cEvent = cEvent
        self.tEvent = cEvent
        self.count = 0
    def csv2xml(self,data,wf):
        pass
    def run():
        count = 1
        while True:
            self.csv2xml(data,wf):
                count +=1
            id count == 100:
                self.cEvent.set()
                self.tEvent.wait()
                self.cEvent.clear()
                count = 0
class TarThread(Thread):
    def __init__(self,cEvent,tEvent):
        Thread.__init__(self)
        self.cEvent = cEvent
        self.tEvent = cEvent
        self.count = 0
        self.setDaemon(True) #设置为守护进程
    def tarXml(self):
        self.count += 1
        tfname = '%d.tar'%self.count
        tf = tarfile.open(tfname,'w:gz')
        for fname in os.listdir('.'):
            if fname.endwith('xml'):
                tf.add(frame)
                os,remove(fname)
        tf.close()
        
        if not tf.members:
            os.remove(tfname)
    def run(self):
        while True:
            self.cEvent.wait() #等待事件
            self.tarXml() #打包
            self.cEvent.clear() #清空当前状态
            self.tEvent.set() #发送消息

共同维护两个 Event,并通过 set 和 wait 来发送消息,通过clear 清除当前状态。

8-4 如何使用线程本地数据

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容