show-me-the-code: 文本处理

第 0004 题:任一个英文的纯文本文件,统计其中的单词出现的个数。

第 0006 题:你有一个目录,放了你一个月的日记,都是 txt,为了避免分词的问题,假设内容都是英文,请统计出你认为每篇日记最重要的词。

第 0007 题:有个目录,里面是你自己写过的程序,统计一下你写过多少行代码。包括空行和注释,但是要分别列出来。

第 0011 题: 敏感词文本文件 filtered_words.txt,里面的内容为以下内容,当用户输入敏感词语时,则打印出 Freedom,否则打印出 Human Rights。

北京
程序员
公务员
领导
牛比
牛逼
你娘
你妈
love
sex
jiangge

第 0012 题: 敏感词文本文件 filtered_words.txt,里面的内容 和 0011题一样,当用户输入敏感词语,则用 星号 * 替换,例如当用户输入「北京是个好城市」,则变成「**是个好城市」。

 

re

    正则表达式设计之初,就是为了处理字符串的,是一个强大的工具,拥有自己独特的语法以及一个独立的处理引擎,功能十分强大,基本所有的开发语言都支持正则表达式,语法基本相同,区别在于不同的编程语言实现的语法数量的不同;

    正则表达式都是经过正则表达式引擎编译之后生成正则表达式对象,然后用生成的正则表达式对象去跟需要匹配的文本进行匹配,得出匹配结果,匹配过程包含了这次成功匹配的信息(匹配的到的字符串、分组以及在文本中的索引)

详细可参考博客:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html

其中写的很详细

    简单的过滤敏感词可用 re 模块匹配,然后替换为 *

 

glob

    Python 中 glob 模块可以查找特定规则的文件路径名, 查找文件可用到三个匹配符:

# *:匹配 0 个或多个字符
# ?:匹配单个字符
# []:匹配指定范围内的字符([0-9] 匹配数字)

glob.glob

    返回所有匹配的文件路径列表,glob.glob(pathname),参数 pathname 定义了文件路径匹配规则:

# -*- coding: utf-8 -*-

improt glob 

# 获取当前目录下所有以 .py 结尾的文件
filelist = glob.glob('./*.py')

glob.iglob

    获取一个可遍历的对象,可逐个获取匹配的文件路径名,iglob 一次获取一个匹配路径,glob 同时获取所有匹配路径

 

with

    with 语句是在 Python 2.5 版本引入的,从 2.6 版本开始成为缺省的功能,with 语句作为 try/finally 编码范式的一种替代,用于对资源访问进行控制的场合,使用 with 需要明报上下文管理器的概念,有了上下文管理器,with 语句才能工作。

上下文管理协议

    包含方法 __enter__() 和 __exit__(),支持该协议的对象要实现这两个方法

上下文管理器

    支持上下文管理协议的对象,这种对象实现了 __enter__() 和 __exit__() 方法,上下文管理器定义执行 with 语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作,通常使用 with 语句调用上下文管理器,也可以通过直接调用方法来使用。

运行时上下文

    由上下文管理器创建,通过上下文管理器的 __enter__() 和 __exit__() 方法实现,__enter__() 方法在语句体执行之前进入运行时上下文,__exit__() 在语句体执行完后从运行时上下文退出。with 语句支持运行时上下文这一概念。

上下文表达式

    with 语句中跟在关键字 with 之后的表达式,该表达式要返回一个上下文管理器对象。

语句体

    with 语句包裹起来的代码块,在执行语句体之前会调用上下文管理器的 __enter__() 方法,执行完语句体之后会执行 __exit__() 方法。

 

基本语法和工作原理

# with 语法格式

with context_expression [as target(s)]:
    with-body

    context_expression 返回一个上下文管理器对象,该对象并不赋值给 as 语句中的 target(s),如果指定了 as,会将上下文管理器的 __enter__() 方法的返回值赋值给 target(s),target(s) 可以是单个变量,或者有“()”括起来的元组。

    Python 对一些内建对象进行改进,加入了对上下文管理器的支持,可以用于 with 语句中,例如可以自动关闭文件、线程锁的自动获取和释放。

# -*- coding: utf-8 -*-

# with 操作文件对象
with open(r'fileName') as somefile:
    for line in somefile:
        print(line)

    当使用了 with 语句,不管在处理文件过程中是否发生了异常,都能保证 with 语句执行完毕后已经关闭了打开的文件句柄,传统 try/finally:

# -*- coding: utf-8 -*-

somefile = open(r'fileName')
try:
    for line in somefile:
        print(line)
finally:
    somefile.close()

    还有 threading、decimal 等模块也加入了对上下文管理协议的支持

with 语句执行过程

context_manager = context_expression
    exit = type(context_manager).__exit__  
    value = type(context_manager).__enter__(context_manager)
    exc = True   # True 表示正常执行,即便有异常也忽略;False 表示重新抛出异常,需要对异常进行处理
    try:
        try:
            target = value  # 如果使用了 as 子句
            with-body     # 执行 with-body
        except:
            # 执行过程中有异常发生
            exc = False
            # 如果 __exit__ 返回 True,则异常被忽略;如果返回 False,则重新抛出异常
            # 由外层代码对异常进行处理
            if not exit(context_manager, *sys.exc_info()):
                raise
    finally:
        # 正常退出,或者通过 statement-body 中的 break/continue/return 语句退出
        # 或者忽略异常退出
        if exc:
            exit(context_manager, None, None, None) 
        # 缺省返回 None,None 在布尔上下文中看做是 False


# 1、执行 context_expression,生成上下文管理器 context_manager
# 2、调用上下文管理器的 __enter__() 方法;如果使用了 as 子句,则将 __enter__() 方法的返回值赋值给 as 子句中的 target(s)
# 3、执行语句体 with-body
# 4、不管是否执行过程中是否发生了异常,执行上下文管理器的 __exit__() 方法,__exit__() 方法负责执行“清理”工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句 break/continue/return,则以 None 作为参数调用 __exit__(None, None, None) ;如果执行过程中出现异常,则使用 sys.exc_info 得到的异常信息为参数调用 __exit__(exc_type, exc_value, exc_traceback)
# 5、出现异常时,如果 __exit__(type, value, traceback) 返回 False,则会重新抛出异常,让with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理

详细可参考:http://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/

 

collections

    collections 是 Python 内建的一个集合模块,提供了很多有用的集合类

namedtuple

    tuple(元组) 可以表示不变集合,例如一个坐标可以表示为:

p = (1, 2)

    但是看到 (1,2)又很难知道这是一个坐标点,而定义一个 class 又显得有点隆重了,这时候就可以使用 namedtuple :

bpython version 0.16 on top of Python 3.5.1 /usr/local/opt/python3/bin/python3.5
>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(1, 2)
>>> p.x
1
>>> p.y
2

# namedtuple 是一个函数,可以用来创建一个自定的 tuple 对象,并且规定了 tuple 元素的个数
# 并可以用属性而不是索引来引用 tuple 的某个元素
>>> isinstance(p, Point)
True
>>> isinstance(p, tuple)
True

# 类似用坐标和半径表示一个圆
>>> Circle = namedtuple('Circle', ['x', 'y', 'r'])

deque

    使用 list 存储数据时,按索引访问元素很快,但是插入和删除元素就很慢了,因为 list 是线性存储,数据量大的时候,插入和删除效率很低。

    deque 是为了高效实现插入和删除操作的双向列表,适用于队列和栈:

>>> from collections import deque
>>> q = deque(['a', 'b', 'c'])
>>> q.append('x')
>>> q.appendleft('y')
>>> q
deque(['y', 'a', 'b', 'c', 'x'])
>>>

     deque 除了实现 list 的 append() 和 pop() 外,还支持 appendleft() 和 popleft(),这样就可以非常高效地往头部添加或删除元素。

defaultdict

    使用 dict 时,如果引用的 Key 不存在,就会抛出 KeyErro,如果希望 key 不存在时,返回一个默认值,就可以使用 defaultdict:

>>> from collections import defaultdict
>>> dd = defaultdict(lambda: 'N/A')
>>> dd['key1'] = 'abc'
>>> dd['key1']
'abc'
>>> dd['key2']
'N/A'
>>>

    默认值是调用函数返回的,函数在创建 defaultdict 对象时传入;

OrderedDict

    使用 dict 时,Key 是无序的,在对 dict 做迭代时,无法确定 Key 的顺序,而保持 Key 顺序,可以用 OrderedDict

>>> from collections import OrderedDict
>>> d = dict([('a', 1), ('b', 2), ('c', 3)])
>>> d
{'c': 3, 'b': 2, 'a': 1}
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
# OrdereDict 的 Key 按照插入的顺序排列,而不是 Key 本身排序

    使用 OrderedDict 还可以实现一个 FIFO(先进先出)的 dict,当超出限制时,先删除最早添加的 Key:

# -*- coding: utf-8 -*-

# 先进先出的 dict
from collections import OrderedDict

# 子类 LastUpdateOrderdDict 继承自父类 OrderedDict
class LastUpdateOrderdDict(OrderedDict):

    def __init__(self, capacity):
        # 继承父类的 __init__() 方法
        super(LastUpdateOrderdDict, self).__init__()
        self._capacity = capacity

    def __setitem__(self, key, value):
        containsKey = 1 if key in self else 0
        if len(self) - containsKey >= self._capacity:
            last = self.popitem(last=False)
            print("remove:", last)
        if containsKey:
            del self[key]
            print('set:', (key, value))
        else:
            print("add:", (key, value))
        OrderedDict.__setitem__(self, key, value)

md = LastUpdateOrderdDict(2)
md['a'] = 1
md['b'] = 2
md['c'] = 3
print(md)



# 运行结果
/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/bin/python3.5 /Users/pengchao/PycharmProjects/untitled3/fifo.py
add: ('a', 1)
add: ('b', 2)
remove: ('a', 1)
add: ('c', 3)
LastUpdateOrderdDict([('b', 2), ('c', 3)])

Process finished with exit code 0

 

Counter

    Counter 是一个简单的计数器,可以用来统计字符出现的个数:

>>> from collections import Counter
>>> c = Counter()
>>> for ch in 'programming':
...     c[ch] = c[ch] + 1
...
>>> c
Counter({'g': 2, 'm': 2, 'r': 2, 'a': 1, 'i': 1, 'o': 1, 'n': 1, 'p': 1})
>>> Counter('programming').most_common()
[('g': 2, 'm': 2, 'r': 2, 'a': 1, 'i': 1, 'o': 1, 'n': 1, 'p': 1})

 

super

    在 Python 类方法中,要想调用父类的某个方法,在 Python 2.2 之前,通常需要定义出来,这样当父类发生变化时,子类需要重新遍历整个类的定义,这样对代码的维护来说是灾难性的。

    从 Python 2.2 开始,引入了一个关键字 super 用来解决这个问题

super(type[, object-or-type])
  Return the superclass of type. If the second argument is omitted the super object
  returned is unbound. If the second argument is an object, isinstance(obj, type) 
  must be true. If the second argument is a type, issubclass(type2, type) must be 
  true. super() only works for new-style classes.
  A typical use for calling a cooperative superclass method is:
   class C(B):
       def meth(self, arg):
           super(C, self).meth(arg)
  New in version 2.2.

    当子类需要使用父类中的某个方法时:

class A(object):    # A must be new-style class
  def __init__(self):
   print "enter A"
   print "leave A"

class B(A):     
  def __init__(self):
   print "enter B"
   # 调用父类 A 中的 __init__() 方法
   super(B, self).__init__()
   print "leave B"

 

习题代码上传至 github

 

转载于:https://my.oschina.net/u/2470065/blog/867820

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值