Python朝花夕拾

多条件比较

使用any/all

if any([33 <= cp <= 47, 58 <= cp <= 64,
91 <= cp <= 96, 123 <= cp <= 126]):
return True

 

二维数组flatten成一维数组

sum(a, [])

 

Q1:HTTP Error 403: Forbidden

python中经常使用urllib2.urlopen函数提取网页源码,但是有些时候这个函数返回的却是:HTTP Error 403: Forbidden,这表明源网站不允许爬虫进行爬取

解决方法:伪装成浏览器进行访问

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import urllib2
url = "http://www.google.com/translate_a/t?client=t&sl=zh-CN&tl=en&q=%E7%94%B7%E5%AD%A9"
#浏览器头
headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
req = urllib2.Request(url=url,headers=headers)
data = urllib2.urlopen(req).read()
print data

这样就可以得到网页源码了~

注:如果源码中中文为乱码,可以使用:

print data.decode("UTF-8")

参见 http://www.geekcome.com/content-10-3101-1.html

 

Q2:文件读写

read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中,readline() 和 readlines()之间的差异是后者一次读取整个文件,像read()一样。readlines()自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for... in ... 结构进行处理。另一方面,readline()每次只读取一行,通常比 readlines()慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用.readline()

注意:f.readline()完成后最后一个字符是 ‘\n’,此时光标已经定位到了下一行的第0个位置,如果需要去除最后的回车键‘\n’,则为

line = f.readline()
line = line[:-1]

也可以用"string".strip('\n')

参见 http://www.cnblogs.com/kaituorensheng/archive/2012/06/05/2537347.html


for line in open('poem.txt'):
  print line
f = open('test.txt', 'r')
#以读方式打开文件
for line in f.readlines():
  print line

 

逐行读取文件内容的三种方法

方法一:

f = open("foo.txt")             # 返回一个文件对象 
line = f.readline()             # 调用文件的 readline()方法 
while line: 
    print line,                 # 后面跟 ',' 将忽略换行符 
    # print(line, end = '')   # 在 Python 3中使用 
    line = f.readline() 
f.close() 

方法二:

代码如下:

for line in open("foo.txt"): 
    print line, 

方法三:

代码如下:

f = open("c:\\1.txt","r") 
lines = f.readlines()#读取全部内容 
for line in lines 
    print line 

 

>>>> welcome_str ="Welcome you"
>>>> welcome_str[0]
'W'
>>> git_list = ["qiwsir","github","io"]
>>> git_list[0]
'qiwsir'

 

Q3:list和str转化

list和str的最大区别是:list是原处可以改变的,str则原处不可变

list和str转化

str.split()

“”.join(list)

>>> line = "Hello.I am qiwsir.Welcome you."
>>> line.split(".")
#以英文的句点为分隔符,得到list ['Hello', 'I am qiwsir', 'Welcome you', '']
>>> line.split(".",1)
#这个1,就是表达了上文中的:If maxsplit is given, at most maxsplit splits are done. ['Hello', 'I am qiwsir.Welcome you.']
>>> name = "Albert Ainstain"
#也有可能用空格来做为分隔符
>>> name.split(" ") ['Albert', 'Ainstain'] join可以说是split的逆运算

从list得到的字符串做切片操作

list[0][1:]  #remove the first character

 

Q4:list对应元素相加

使用zip函数

zip就是把2个数组糅在一起
x=[1, 2, 3, 4, 5 ]
y=[6, 7, 8, 9, 10]
zip(x, y)就得到了
[(1, 6), (2, 7), (3, 8), (4, 9), (5, 10)]

list12 = [x+y for x,y in zip(list1,list2)]

求l1=[[1,2],[3,4],[5,6]]对应元素的和

>>> l1=[[1,2],[3,4],[5,6]]
>>> list(map(sum,zip(*l1)))
[9, 12]

zip参考:http://www.lfyzjck.com/python-zip/

对于将两个等长的列表合并成字典:dict(zip(list1, list2))

 

Q5:判断数据类型

import types
type(x) is types.IntType # 判断是否int 类型
type(x) is types.StringType #是否string类型
types.ListType == type(text)

 

Q6:三目运算符

true_part if condition else false_part

>>> 1 if True else 0
1
>>> 1 if False else 0
0

Q7:list去重

http://www.jb51.net/article/55342.htm

ids = [1,4,3,3,4,2,3,4,5,6,1]
news_ids = list(set(ids))
news_ids.sort(ids.index)

 

Q8:Python的函数指针

#Icmp----Generates some ICMP traffic
def matchIcmp(json_data):
  if json_data['network']['icmp']:
    print 'Generates some ICMP traffic'
func_sets=[matchEntropy,matchIcmp,matchIrc,matchHttp,matchSmtp,matchDomain,matchFile,matchRegister,matchMutex,matchApi]
for func in func_sets:
   func(json_data)
#模块中,类外的函数指针调用
def hwFunc1(x):
  print("waleking's func1")
def hwFunc2(x):
  print("%s" %(x+1))
  print("waleking's func2")
funcSets={"func1":hwFunc1,"func2":hwFunc2}
funcSets["func1"](1)


Q9:TypeError: ‘NoneType’ object is not iterable

原因:最终所被调用的函数所返回的值,和返回值赋值给的变量,不匹配。

 

Q10:Python按照书写顺序输出字典中的元素

使用dict时,Key是无序的。在对dict做迭代时,我们无法确定Key的顺序。

如果要保持Key的顺序,可以用OrderedDict

>>> from collections import OrderedDict
>>> d = dict([('a', 1), ('b', 2), ('c', 3)])
>>> d # dict的Key是无序的
{'a': 1, 'c': 3, 'b': 2}
>>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
>>> od # OrderedDict的Key是有序的
OrderedDict([('a', 1), ('b', 2), ('c', 3)])

注意,OrderedDict的Key会按照插入的顺序排列,不是Key本身排序:

>>> od = OrderedDict()
>>> od['z'] = 1
>>> od['y'] = 2
>>> od['x'] = 3
>>> od.keys() # 按照插入的Key的顺序返回
['z', 'y', 'x']

reference:http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001411031239400f7181f65f33a4623bc42276a605debf6000

 

Q11:json相关

load(s):文件——>字典

REPORT_PATH = "/tmp/report.json"
method1: result1 = json.load(open(REPORT_PATH))

method2: result2 = json.loads(open(REPORT_PATH ).read())
dump:字典——> 文件
REPORT_PATH = "/tmp/report.json"
results = {“123”: 345, “中文”:”内容”}
json.dump(results, report, ensure_ascii=False, sort_keys=False, indent=4, encoding=”utf-8”)
dumps:字典——>字符串
json.dumps(results , ensure_ascii=False, indent=4, encoding=”utf-8”))
注:涉及到中文的dump(s)务必加上ensure_ascii=False参数,否则会出现乱码问题

 

Q12:ERROR: Missing dependency: No module named xxx

python 将一个文件夹作为 package 对待,那么这个文件夹中必须包含一个名为__init__.py 的文件,即使它是空的。即 import 文件夹名

如果sys.path.append()添加路径,则导入模块时会优先导入pip安装的模块,在查找sys.path.append添加的模块,如果同名,可能出现明明自己在模块中已经定义了但是搜索不到。


reference:http://zengrong.net/post/2192.htm

 

Q13:默认参数的坑

def add_end(L=[]):
    L.append('END')
    return L

>>> add_end()
['END']
>>> add_end()
['END', 'END']
 

原因:Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。

所以,定义默认参数要牢记一点:默认参数必须指向不变对象!

要修改上面的例子,我们可以用None这个不变对象来实现:

def add_end(L=None):
    if L is None:
        L = []
    L.append('END')
    return L
>>> add_end()
['END']
>>> add_end()
['END']

为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。

 

Q14:可变参数

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum

定义可变参数和定义list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:

>>> calc(1, 2)
5
>>> calc()
0

如果已经有一个list或者tuple,要调用一个可变参数怎么办?Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去

>>> nums = [1, 2, 3]
>>> calc(*nums)
14

 

Q15:关键字参数

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。请看示例:

def person(name, age, **kw):
    print 'name:', name, 'age:', age, 'other:', kw

函数person除了必选参数nameage外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数:

>>> person('Michael', 30)
name: Michael age: 30 other: {}

也可以传入任意个数的关键字参数:

>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
 
>>> kw = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **kw)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
 
>>> args = (1, 2, 3, 4)
>>> kw = {'x': 99}
>>> func(*args, **kw)
a = 1 b = 2 c = 3 args = (4,) kw = {'x': 99}

 

Q16:尾递归

普通递归:
def fact(n):
    if n==1:
        return 1
    return n * fact(n - 1)
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
 
尾递归:尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
        遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。
def fact_iter(num, product=1):
    if num == 1:
        return product
    return fact_iter(num - 1, num * product)
===> fact_iter(5, 1)
===> fact_iter(4, 5)
===> fact_iter(3, 20)
===> fact_iter(2, 60)
===> fact_iter(1, 120)
===> 120

 

Q17:logging相关

对于一个模块中,主脚本初始化logging之后,其他脚本可以通过log = logging.getLogger(__name__)来进行调用,此处有一个坑,就是需要在主脚本中设置log = logging.getLogger()而不能带有参数(默认是None),

1. logging对象其实是一个树形结构,每个创建的logging对象都是root logging对象的孩子结点。当使用logging模块的getLogger(name=None)函数构造logging对象的时候,如果name为None,这样会产生一个root logging对象。如果name中含有.,比如name = 'a.b.c',通过这种方式会产生3个logging对象,分别为c、b、a,c->b->a->root,root树的根结点,a为root的孩子结点,b为a的孩子结点,c为a的孩子结点,依次类推。

2. root结点是全局的,虽然这过程中涉及到多个模块,但是它们会共享一个root结点。

3. 每个logging对象打LOG的时候,也会把LOG信息传递到传递到上层logging对象中,对于c->b->a->root这种情况,这个LOG其实会打4次,以c、b、a、root循序依次打一个LOG。

 

Q18: subprocess函数中shell问题

使用了shell=True这个参数。
这个时候,我们使用一整个字符串,而不是一个表来运行子进程。
Python将先运行一个shell,再用这个shell来解释这整个字符串。

rc = subprocess.call(["ls","-l"])

out = subprocess.call("ls -l", shell=True)

args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (e.g. to permit spaces in file names). If passing a single string, eithershell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.

尽量不用带shell的函数

 

Q19: 遍历列表统计每个单词出现的个数,返回字典,key为单词,value为对应的次数

最low的方法:

dict_api = {}

for api in apis:
    if api in dict_api:
        dict_api[api] += 1
    else:
        dict_api[api] = 1

优雅的方法:

l = ['a', 'a', 'c', 'b', 'c']
dict((k, l.count(k)) for k in set(l))

第三方库:

from collections import Counter

dict(Counter(l))

Counter相关,Counter实际上也是dict的一个子类:

创建

>>> c = Counter() # 创建一个空的Counter类

>>> c = Counter('gallahad') # 从一个可iterable对象(list、tuple、dict、字符串等)创建

>>> c = Counter({'a': 4, 'b': 2}) # 从一个字典对象创建

>>> c = Counter(a=4, b=2) # 从一组键值对创建

 

当所访问的键不存在时,返回0,而不是KeyError;否则返回它的计数。

>>> c = Counter("abcdefgab")

>>> c["a"]

2

>>> c["c"]

1

>>> c["h"]

0

计数器的更新(update和subtract)

reference: http://www.pythoner.com/205.html

字典按value排序:

sorted_api = sorted(dict_api.iteritems(), key=lambda d: d[1], reverse=True)
返回列表
 

字典合并:

FIVUWZ}O(7$XW78B7__QJ20

BKFIKLNQL9HGI[QM]K{R]%B

posted on 2015-08-20 09:40  月流霜  阅读(365)  评论(0编辑  收藏  举报