美文网首页python学习专题
《Python高级编程技巧》学习笔记

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

作者: 软体动物Ai | 来源:发表于2017-01-07 10:03 被阅读214次

    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 如何使用线程本地数据

    相关文章

      网友评论

        本文标题:《Python高级编程技巧》学习笔记

        本文链接:https://www.haomeiwen.com/subject/tyuavttx.html