分享Python 的十个小技巧

发布时间:2019-08-31 09:43:33编辑:auto阅读(1566)

      一. 列表、字典、集合、元组的使用

      from random import randint, sample

      # 列表解析

      data = [randint(-10, 10) for _ in xrange(10)]

      filter(lambda x: x >= 0, data)

      [x for x in data if x >= 0] #最快速

      # 字典解析

      d = {x: randint(60, 100) for x in xrange(1,21)}

      {k : v for k, v in d.iteritems() if v > 90}

      # 集合解析

      s = set(data)

      {x for x in s if x % 3 ==0}

      # 元组

      student = ('Jim', 16, 'male', 'jim@qq.com')

      # 1. enum

      NAME, AGE, SEX, EMAIL = xrange(4)

      print student[NAME]

      # 2.

      from collections import namedtuple

      Student = namedtuuple('Student', ['name', 'age', 'sex', 'email'])

      s2 = Student('Tom', 16, 'mail', 'tom@qq.com')

      print s2.name

      # 统计列表的重复元素

      li = [randint(0, 20) for _ in xrange(30)]

      d = dict.fromkeys(li, 0)

      # 1.

      for x in li: d[x] += 1

      # 2.

      from collections import Counter

      d2 = Counter(li)

      d2.most_common(3) #重复数最高的三个元素

      # 字典根据值value排序

      sorted([3, 1, 5]) #排序列表

      (97, 'a') > (88, 'b') # 元组的比较,每个元素从开始比较

      d = {x: randint(60, 100) for x in 'abcde'}

      # 1.

      data = zip(d.itervalues(), d.iterkeys())

      sorted(data)

      # 2.

      sorted(d.items(), key=lambda x: x[1])

      # 多个字典中的公共键

      sample('abcdefg', 3)

      sample('abcdefg', randint(3,6)) # 随机取出几个元素

      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))}

      # 1.

      res = []

      for k in s1: if k in s2 and k in s3: res.append(k) # res.pop(k)

      # 2. 使用集合

      res = s1.viewkeys() & s2.viewkeys() & s3.viewkeys()

      # 3.

      m1 = map(dict.viewkeys, [s1, s2, s3])

      res = reduce(lambda a, b: a & b, m1)

      # 保持字典有序

      d = {'Jim':(1, 35), 'Leo':(2, 38), 'Tom':(3, 44)}

      from collections import OrderedDict

      d = OrderedDict() #按进入字典的顺序打印

      d['Jim'] = (1,35)

      d['Leo'] = (2,38)

      d['Tom'] = (3,44)

      from time import time

      start = time()

      raw_input() #等待输入

      # ...

      timesecond = time() - start

      # 历史记录

      # 1. 用队列存储

      from collections import deque

      q = deque([], 5)

      q.append(1) # 达到长度后,先进先出

      li = list(q) # 转换成列表类型

      # 2. 将q存到文件中

      import pickle

      pickle.dump(q, open('test','w'))

      q2 = pickle.load(open('test','r'))

      二. 迭代器、生成器

      # 实现可迭代对象、迭代器对象

      # 用时访问 并封装到一个对象中

      # 可迭代对象

      li = [1,2,3,4]

      str= 'abcde'

      # 迭代器

      iterl = iter(li) # li.__iter__()

      iters = iter(str) # str.__getitem__()

      iterl.next()

      # 1. 城市天气的迭代器和可迭代对象

      from collections import Iterable, Iterator

      class WIterator(Iterator):

      def __init__(self, cities):

      self.cities = cities

      self.index = 0

      def getWeather(city):

      import requests

      r = requests.get(u'http://wthrcdn.etouch.cn/weather_mini?city=' + city)

      data = r.json()['data']['forecast'][0]

      return '%s: %s, %s' % (city, data['low'], data['high'])

      def next(self):

      if self.index == len(self.cities)

      raise StopIteration

      city = self.cities[self.index]

      self.index += 1

      return self.getWeather(city)

      class WIterable(Iterable):

      def __init__(self, cities):

      self.cities = cities

      def __iter__(self):

      return WIterator(self.cities)

      for x in WIterable([u'北京', u'长沙', u'广州']):

      print x

      # 2. 使用生成器函数实现可迭代对象

      def f():

      print 'in f(), 1'

      yield 1

      print 'in f(), 2'

      yield 2

      g = f() # g.__iter__()

      for i in g: print i

      class PrintNumbers:

      def __init__(self, start, end):

      self.start = start

      self.end = end

      def isPrimeNum(self, k):

      if k % 2 == 0:

      return True

      else:

      return False

      def __iter__(self):

      for k in xrange(self.start, self.end+1):

      if self.isPrimeNum(k):

      yield k

      for x in PrintNumbers(1, 100): print x

      # 进行反向迭代

      li = [1,2,3,4,5]

      li.reverse() # 改变原来列表

      li[::-1] # 切片,和原来列表等大的新列表

      ll = li.reversed(li) # 列表反向迭代

      for i in ll: print i

      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.enf

      while t >= self.start:

      yield t

      t -= self.step

      # 正向迭代

      for i in FloatRange(1.0, 4.0, 0.5): print x

      # 反向迭代

      for i in reversed(FloatRange(1.0, 4.0, 0.5)): print x

      # 对迭代器做切片操作

      from itertools import islice

      # islice()

      li = range(20)

      t = iter(li)

      for x in islice(t, 5, 10): print x # 会消耗原来的迭代对象

      # 在一个for中迭代多个可迭代对象

      chinese = [randint(60,100) for _ in xrange(40)]

      math = [randint(60,100) for _ in xrange(40)]

      english = [randint(60,100) for _ in xrange(40)]

      for in in xrange(len(math)):

      print chinese[i] + math[i] + english[i]

      total = []

      # 并行多个可迭代对象

      for c, m, e in zip(chiness, math, english)

      print c+m+e

      # 1. 串连多个迭代对象

      from itertools import chain

      c1 = [randint(60,100) for _ in xrange(40)]

      c2 = [randint(60,100) for _ in xrange(42)]

      c3 = [randint(60,100) for _ in xrange(45)]

      for s in chain(c1, c2, c3):

      if s > 90: print s

      三. 字符串

      # 拆分含多种分隔符的字符串

      s = "fwerf sd123 ^sdf dfdsf*d dsf 123"

      s.split(“xy”) #默认以空格分割,或以参数分割

      res = s.split(";")

      map(lambda x: x.split("|"), res) # 以";"和"|"分割的二维数组

      t = []

      map(lambda x: t.extend(x.split("|")), res) # 二维元素放到t中

      # 1.

      def aSplit(s, ds):

      res = [s]

      for d in ds:

      t = []

      map(lambda x: t.extend(x.split(d)), res)

      res = t

      return res

      print aSplit(s, " ^*") # 会存在空的元素

      # 2. 正则表达式

      import re

      re.split(r'[,;|]+', s)

      # 判断字符串a是否以b开头或结尾

      #s.startswith() s.endswith() 接收单个字符串或字符串元组

      import os, stat

      files = [name for name in os.listdir(".") if name.endswith(('.sh', '.py'))]

      # 调整字符串中文本的格式

      #日志中'yyyy-mm-dd' 改为 'mm/dd/yyyy'

      import re

      log = open("/var/log/dpkg.log").read()

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

      re.sub('(?P\d{4})-(?P\d{2})-(?P\d{2})', r'\g/\g/\g', log)

      # 多个小字符串拼接成大字符串

      s1 = "abcde"

      s2 = "12345"

      s1 + s2 # str.__add__(s1, s2) str.__gt__(s1, s2) 运算符重载

      s = ""

      for p in pl: s += p # 变量多时,临时变量开销大,资源浪费

      s.join(s1) # 参数可为字符串,可为列表

      li = ['avc', 123, 'xyz', 456]

      ''.join([str(x) for x in li]) #列表解析,会生成一个列表,开销大

      ''.join(str(x) for x in li) #生成器, (str(x) for x in li) 作为参数是括号省略

      # 字符串格式对齐

      # str.ljust() str.rjust() str.center()

      s = "abc"

      s.ljust(10 ,'=') # 左对齐,填充=

      s.center(10)

      format(s, '<20') # 左对齐

      format(s, '>20') # 右对齐

      format(s, '^20') # 居中

      # 去掉字符串中不需要的字符

      s = ' -------sd dfadf 2332 +++++++++'

      s.strip(' -+')

      s.lstrip()

      s.rstirp()

      # 删除固定位置的字符,拼接切片

      s[:3]+ s[4:]

      # 替换

      s.replace('\t', '')

      import re

      re.sub('[\t\r]', '', s)

      s = 'abc123e3rxyz'

      #s.translate()

      import string

      tr = string.maketrans('abcxyz', 'xyzabc')

      s.translate(tr)

      s = 'abc\rdfd\n234234\t'

      s.translate(None, '\r\t\n')

      四. 文件读写

      # python2 str unicode

      # python3 bytes str

      # python2

      s = u'你好'

      s.encode('utf8') #存储到文件中的格式

      f = open('hello.txt', 'w')

      f.write(s.encode('utf8'))

      f.close()

      f = open('hello.txt', 'r')

      t = f.read().decode('utf8') # 你好

      f.close()

      # python3 字符串就是unicode

      strb = b'asdfasdfsdg'

      s = '你好'

      f = open('hello2.txt', 'wt', encoding='utf8') # 自动完成编解码

      f.write(s)

      f.close()

      f = open('hello2.txt', 'rt', encoding='utf8')

      s = f.read()

      f.close()

      # 处理二进制文件 处理音频文件,将音量调小保存

      f = open('demo.wav', 'rb')

      info = f.read(44) #文件头

      import struct

      struct.unpack('h',info[22:24]) #处理文件头 数据运算

      struct.unpack('i',infi[24:28])

      f.seek(0,2)

      f.tell()

      n = (f.tell()-44) /2

      import array

      buf = array.array('h', (0 for _ in xrange(n)))

      f.seek(44)

      f.readinto(buf)

      for i in xrange(n): buf[i] /= 8

      f2 = open('demo2.wav', 'wb')

      f2.write(info)

      buf.tofile(f2)

      f2.close()

      # 使用临时文件

      # 自动删除,不占内存

      from tempfile import TemporaryFile, NamedTemporaryFile

      f = TemporaryFile() # 系统文件系统找不到

      f.write('abcddee'*100000)

      f.seek(0)

      f.read(100)

      ntf = NamedTemporaryFile(delete=False) # 能找到文件,默认关闭以后会删除文件

      fname = nft.name

      # 设置文件的缓冲

      # I/O 操作以块为单位,如4096字节一个块

      f = open('test.txt', 'w', buffering=2048) # 全缓冲,要写满缓冲才会写到文件中

      f = open('test.txt', 'w', buffering=1) # 行缓冲,\n就会写文件

      f = open('test.txt', 'w', buffering=1) # 无缓冲,实时写

      f.write('abc')

      # 将文件映射到内存

      import mmap

      f = open('demo.bn','r+b')

      f.fileno()

      m = mmap.mmap(f.fileno(), 0, access=mmpa.ACCESS_WRITE, offset=mmap.PAGESIZE)

      # 得到字节数组

      m[4:8] = '\xff'*4 # 修改直接改变文件内容

      # 读写csv数据

      from urllib import urlretrieve

      urlretrieve('http://table.finance.yahoo.com/table.csv?s=000001.sz', 'pingan.csv')

      rf = open('pingan.csv', 'rb')

      import csv

      reader = csv.reader(rf)

      header = reader.next()

      wf = open('pingan_c.csv', 'wb')

      writer = csv.writeer(wf)

      writer.writerow(header)

      rf.close()

      wf.close()

      # 读写json数据

      import requests

      import json

      from record import Record

      record = Record(channel=1)

      audioData = record.record(2)

      from secret import API_KEY, SECRET_KEY

      authUrl = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + API_KEY + "&client_secret=" + SECRET_KEY

      response = requests.get(authUrl)

      res = json.loads(response.content)

      token = res['access_token']

      #百度语音识别

      cuid = 'xxxxxxxxxxxxx'

      srvUrl = 'http://vop.baidu.com/server_api?cuid=' + cuid + '&token=' + token

      heepHeader = {'Content-Type': 'audio/wav; rate = 8000'}

      response = requests.post(srvUrl, headers=httpHeader, data=audioData)

      res = json.loads(response.content)

      text = res['result'][0]

      print text

      # json.dumps() python对象(列表、字典等)转换成json字符串

      # json.dumps(data, sort_keys=True)

      # json.loads() json字符串转换成python对象

      with open('demo.json', 'wb') as f:

      json.dump(l, f) # 将l数据写到文件

      # 构建xml文档

      from xml.etree.ElementTree import parse

      with open('demo.xml') with f:

      et = parse(f)

      root = et.getroot()

      root.tag

      root.attrib

      root.text

      #root.getchildren()

      for child in root:

      print child.get('name')

      root.find('country')

      root.findall('country') # 直接子元素

      for e in root.iterfind('country'):

      print e.get('name')

      from xml.etree.ElementTree import Element, ElementTree, tostring

      e = Element('Data')

      e.set('name', 'abc')

      e2 = Element('Row')

      e3 = Element('Open')

      e3.text = '8.80'

      e2.append(e3)

      e.append(e2)

      tostring(e)

      et = ElementTree(e)

      et.write('demo.xml')

      # 读写excel文件

      import xlrd, xlwt

      book = xlrd.open_workbook('demo.xls')

      book.sheets()

      sheet = book.sheet_by_index(0)

      rows = sheet.nrows

      cols = sheet.ncols

      cell = sheet.cell(0,0) #(0,0)单元格

      cell.ctype

      cell.value

      row = sheet.row(1) #cell对象列表

      data = sheet.row_values(1, 1) #第1列跳过第一格的值列表

      sheet.put_cell(0, cols, xlrd.XL_CELL_TEXT, u'Total', None)

      wbook = xlwt.Workbook()

      wsheet = wbook.add_sheet('sheet1')

      style = xlwt.easyxf('align: vertical center, horizontal center')

      wsheet.write(rows,cols, sheet.cell_value(rows,cols), style)

      wsheet.save('output.xls')

      五. 派生内置不可变类型并修改其实例化行为

      class IntTuple(tuple):

      def __new__(cls, iterable): #先于__init__()调用

      g = (x for x in iterable if isinstance(x, int) and x > 0)

      super(IntTuple, cls).__new__(cls, g)

      def __init__(self, iterable):

      # 此时如果过滤iterable 无法过滤成功

      super(IntTuple, self).__init__(iterable)

      t = IntTuple([1, -1, 'abc', 6, ['x', 'y'], 3])

      print t 无锡妇科医院排名 http://www.csyhjlyy.com/

      六. 使用描述符对实例属性做类型检查

      # 描述符: 包含 __get__() __set__() __delete__() 函数的类

      class Attr(object):

      def __init__(self, name, type_):

      self.name = name

      self.type_= type_

      def __get__(self, instance, cls):

      return instanse.__dict__[self.name]

      def __set__(self, instance, value):

      if not isinstance(value, self.type_):

      raise TypeError('expected %s' % self.type_)

      instance.__dict__[self.name] = value

      def __delete__(self, instance):

      del instance.__dict__[self.name]

      class Person(object):

      name = Attr('name', str)

      age = Attr('age', int)

      hgt = Attr('height', float)

      p = Person()

      p.name = 'Bob'

      print p.name

      p.age = '17' #会抛出异常

      七. 在环状数据结构中管理内存

      import sys

      class A(object):

      def __del__(self): # 当引用次数变为0时,调用析构函数

      print 'in A.__del__'

      a = A()

      a2 = a

      print sys.getrefcount(a) - 1 # 查看对象a的引用次数,参数名也引用了对象,要-1

      del a

      del a2

      # 循环引用

      class Data(object): # Data类保存Node对象引用

      def __init__(self, value, owner):

      self.owner = owner

      self.value = value

      def __str__(self):

      return "%s's data, value is %s" % (self.owner, self.value)

      def __del__(self):

      print 'in Data.__del__'

      class Node(object): # Node类调用Data对象

      def __init__(self, valu):

      self.data = Data(value, self)

      def __del__(self):

      print 'in Node.__del__'

      node = Node(100)

      del node # 此时Data Node不会被回收掉

      raw_input('wait...')

      # 使用弱引用

      import weakref

      a_wref = weakref.ref(a)

      a2 = a_wref()

      class Data(object): # Data类保存Node对象引用

      def __init__(self, value, owner):

      self.owner = weakref.ref(owner) # 弱引用

      self.value = value

      def __str__(self):

      return "%s's data, value is %s" % (self.owner(), self.value)

      def __del__(self):

      print 'in Data.__del__'

      node2 = node(100)

      del node2 # 此时Data Node将被回收

      八. 通过实例方法名的字符串调用方法

      # Circle Triangle Trctangle 求面积的方法名都不同

      # 通过传方法名来调用不同的方法

      # 1. getattr 获取对象属性,方法名也是属性

      from lib1 import Circle

      from lib2 import Triangle

      from lib3 import Tectangle

      def getArea(shape):

      for name in ('area', 'getArea', get_area):

      f = getattr(shape, name , None)

      if f:

      return f()

      shape1 = Circle(2)

      shape2 = Tirangle(3,4,5)

      shape3 = Rectangle(6,4)

      shapes = [shape1, shape2, shape3]

      print map(getArea, shapes)

      # 2. 使用opreator标准库

      from opreator import methodcaller

      s = "abc123abc456"

      s.find('abc', 4)

      methodcaller('find', 'abc', 4)(s)

      九. 为创建大量实例节省内存

      class Player(object):

      def __init__(self, uid, name, status=0, level=1):

      self.uid = uid

      self.name = name

      self.stat = status

      self.level = level

      class Player2(object):

      __slots__ = ['uid', 'name', 'stat', 'level']

      def __init__(self, uid, name, status=0, level=1):

      self.uid = uid

      self.name = name

      self.stat = status

      self.level = level

      p1 = Player('0001', 'Jim')

      p2 = Player2('0002', 'Tom')

      # p1 bi p2 多两个属性 __dict__ __weakref__

      # __dict__ 字典,为实例动态绑定解除新属性

      # p2 则不能动态绑定属性

      # __slots__ 阻止了该功能

      十. 让对象支持上下文管理

      # 要使用上下文管理,类中要定义 __enter__ __exit__方法,分别在with开始和结束时调用

      class test(object):

      ...

      def __enter__(self):

      pass

      def __exit__(self, exc_type, exc_val, exc_tb):

      pass

      with test() as k:

      pass


关键字