[翻译整理]stackoverflow python 百问
更新到github了,地址:https://github.com/wklken/stackoverflow-py-top-qa
后续这里不更新了哈
进度40%,最近有点犯懒
刚刚注册,好东西
查看了下前面(vote前15页,挑了下,vote都是100+的样子,大概120个)的问题,链接, 大体梳理了下,本来想放一页搞定,奈何排版太乱,按类型分了下
第一页的前几个比较长,目测都有中文翻译版本,大家可以网上搜下
其他问题相对比较杂,有些简单,有些复杂,拉过来参考参考也不错
总结整理,复习印证(注意,合并了每个问题的多个答案,但是时间仓促,疏漏难免,感兴趣问题直接点链接看原文吧)
基本数据结构(列表,元组,字典等)
判断一个列表为空得最佳实践
问题 链接
答案:
if not a:
print "List is empty"
#不要用len(a)来判断
为什么是string.join(list)而不是list.join(string)
问题 链接
my_list = ["Hello", "world"]
print "-".join(my_list)
#为什么不是 my_list.join("-") 。。。。这个....
答案:
因为所有可迭代对象都可以被连接,但是连接者总是字符串
如何合并两个列表
问题 链接
listone = [1,2,3]
listtwo = [4,5,6]
#outcome we expect: mergedlist == [1, 2, 3, 4, 5, 6]
1.不考虑顺序(原来问题不是很明确)
listone + listtwo
#linstone.extend(listtwo)也行,就是会修改listone
2.考虑顺序做些处理
>>> listone = [1,2,3]
>>> listtwo = [4,5,6]
>>> import itertools
>>> for item in itertools.chain(listone, listtwo):
... print item
...
1
2
3
4
5
6
如何扁平一个二维数组
问题 链接
l = [[1,2,3],[4,5,6], [7], [8,9]]
变为[1, 2, 3, 4, 5, 6, 4, 5, 6, 7, 8, 9]
列表解析
[item for sublist in l for item in sublist]
itertools
>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))
# python >= 2.6
>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))
sum
sum(l, [])
如何获取一个列表的长度
问题 链接
python中是不是只有这种方法可以获取长度?语法很奇怪
arr.__len__()
应该使用这种方式
mylist = [1,2,3,4,5]
len(mylist)
这样做法,不需要对每个容器都定义一个.length()方法,你可以使用len()检查所有实现了__len__()方法的对象
Python中如何复制一个列表
问题 链接
可以用切片的方法
new_list = old_list[:]
可以使用list()函数
new_list = list(old_list)
可以使用copy.copy(),比list()稍慢,因为它首先去查询old_list的数据类型
import copy
new_list = copy.copy(old_list)
如果列表中包含对象,可以使用copy.deepcopy(), 所有方法中最慢,但有时候无法避免
import copy
new_list = copy.deepcopy(old_list)
例子:
import copy
class Foo(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return str(self.val)
foo = Foo(1)
a = ['foo', foo]
b = a[:]
c = list(a)
d = copy.copy(a)
e = copy.deepcopy(a)
# edit orignal list and instance
a.append('baz')
foo.val = 5
print "original: %r\n slice: %r\n list(): %r\n copy: %r\n deepcopy: %r" \
% (a, b, c, d, e)
结果:
original: ['foo', 5, 'baz']
slice: ['foo', 5]
list(): ['foo', 5]
copy: ['foo', 5]
deepcopy: ['foo', 1]
效率简单比较
10.59 - copy.deepcopy(old_list)
10.16 - pure python Copy() method copying classes with deepcopy
1.488 - pure python Copy() method not copying classes (only dicts/lists/tuples)
0.325 - for item in old_list: new_list.append(item)
0.217 - [i for i in old_list] (a list comprehension)
0.186 - copy.copy(old_list)
0.075 - list(old_list)
0.053 - new_list = []; new_list.extend(old_list)
0.039 - old_list[:] (list slicing)
列表的append和extend的区别
问题 链接
>>> x = [1, 2]
>>> x.append(3)
>>> x
[1, 2, 3]
>>> x.append([4,5])
>>> x
[1, 2, 3, [4, 5]]
>>>
>>> x = [1, 2, 3]
>>> x.extend([4, 5])
>>> x
[1, 2, 3, 4, 5]
如何随机地从列表中抽取变量
问题 链接
foo = ['a', 'b', 'c', 'd', 'e']
from random import choice
print choice(foo)
如何利用下标从列表中删除一个元素
问题 链接
1.del
In [9]: a = range(10)
In [10]: a
Out[10]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [11]: del a[-1]
In [12]: a
Out[12]: [0, 1, 2, 3, 4, 5, 6, 7, 8]
2.pop
a = ['a', 'b', 'c', 'd']
a.pop(1)
# now a is ['a', 'c', 'd']
a = ['a', 'b', 'c', 'd']
a.pop()
# now a is ['a', 'b', 'c']
获取列表的最后一个元素
问题 链接
囧
result = l[-1]
result = l.pop()
序列的切片操作
问题 链接
It’s pretty simple really: 很简单:
a[start:end] # start 到 end-1
a[start:] # start 到 末尾
a[:end] # 0 到 end-1
a[:] # 整个列表的拷贝
还有一个step变量,控制步长,可在上面语法中使用
a[start🔚step] # start through not past end, by step
注意,左闭右开
其他特点,开始或结束下标可能是负数,表示从序列末尾开始计算而非从头开始计算,所以
a[-1] # 最后一个元素
a[-2:] # 最后两个元素
a[:-2] # 除了最后两个元素
Python对程序员很友好,如果序列中存在的元素数量少于你要的,例如,你请求 a[:-2] 但是a只有一个元素,你会得到一个空列表,而不是一个错误.有时候你或许希望返回的是一个错误,所以你必须知道这点
如何将一个列表切分成若干个长度相同的子序列
问题 链接
想要得到这样的效果
l = range(1, 1000)
print chunks(l, 10) -> [ [ 1..10 ], [ 11..20 ], .., [ 991..999 ] ]
使用yield:
def chunks(l, n):
""" Yield successive n-sized chunks from l.
"""
for i in xrange(0, len(l), n):
yield l[i:i+n]
list(chunks(range(10, 75), 10))
直接处理
def chunks(l, n):
return [l[i:i+n] for i in range(0, len(l), n)]
使用列表解析创建一个字典
问题 链接
python 2.6
d = dict((key, value) for (key, value) in sequence)
python 2.7+ or 3, 使用 字典解析语法
d = {key: value for (key, value) in sequence}
使用"in"还是"has_key()"
问题 链接
d = {'a': 1, 'b': 2}
'a' in d
True
or:
d = {'a': 1, 'b': 2}
d.has_key('a')
True
哪种更好
in更pythonic, 另外 has_key()在Python3.x中已经被移除
字典默认值
问题 链接
和问题有点偏
#获取时,如不存在,得到默认值
d.get(key, 0)
#设置时,若key不存在,设置默认值,已存在,返回已存在value
d.setdefault(key, []).append(new_element)
#初始即默认值
from collections import defaultdict
d = defaultdict(lambda: 0)
#or d = defaultdict(int)
如何给字典添加一个值
问题 链接
#### Making a dictionary ####
data = {}
# OR #
data = dict()
#### Initially adding values ####
data = {'a':1,'b':2,'c':3}
# OR #
data = dict(a=1, b=2, c=3)
#### Inserting/Updating value ####
data['a']=1 # updates if 'a' exists, else adds 'a'
# OR #
data.update({'a':1})
# OR #
data.update(dict(a=1))
#### Merging 2 dictionaries ####
data.update(data2) # Where data2 is also a dict.
如何将字段转换成一个object,然后使用对象-属性的方式读取
问题 链接
有dict
>>> d = {'a': 1, 'b': {'c': 2}, 'd': ["hi", {'foo': "bar"}]}}
想用这种方式访问
>>> x = dict2obj(d)
>>> x.a
1
>>> x.b.c
2
>>> x.d[1].foo
bar
使用namedtuple
>>> from collections import namedtuple
>>> MyStruct = namedtuple('MyStruct', 'a b d')
>>> s = MyStruct(a=1, b={'c': 2}, d=['hi'])
>>> s
MyStruct(a=1, b={'c': 2}, d=['hi'])
>>> s.a
1
>>> s.b
{'c': 2}
>>> s.c
>>> s.d
['hi']
使用类
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
>>> args = {'a': 1, 'b': 2}
>>> s = Struct(**args)
>>> s
<__main__.Struct instance at 0x01D6A738>
>>> s.a
1
>>> s.b
2
字符串,文件
字符如何转为小写
问题 链接
s = "Kilometer"
print(s.lower())
如何创建不存在的目录结构
问题 链接
if not os.path.exists(directory):
os.makedirs(directory)
需要注意的是,当目录在exists和makedirs两个函数调用之间被创建时,makedirs将抛出OSError
如何拷贝一个文件
问题 链接
shutil模块
copyfile(src, dst)
将src文件内容拷贝到dst,目标文件夹必须可写,否则将抛出IOError异常
如果目标文件已存在,将被覆盖
另外特殊文件,想字符文件,块设备文件,无法用这个方法进行拷贝
src/dst是字符串
字符串转为float/int
>>> a = "545.2222"
>>> float(a)
545.2222
>>> int(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '545.2222'
>>> int(float(a))
545
>>> int('544')
544
另一种,用 ast模块
>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
如何反向输出一个字符串
问题 链接
做法
>>> 'hello world'[::-1]
'dlrow olleh'
如何随机生成大写字母和数字组成的字符串
6U1S75
4Z4UKK
U911K4
解决
import string, random
''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(N))
逐行读文件去除换行符(perl chomp line)
读一个文件,如何获取每一行内容(不包括换行符)
比较pythonic的做法:
>>> text = "line 1\nline 2\r\nline 3\nline 4"
>>> text.splitlines()
['line 1', 'line 2', 'line 3', 'line 4']
用rstrip,(rstrip/lstrip/strip)
#去除了空白+换行
>>> 'test string \n'.rstrip()
'test string'
#只去换行
>>> 'test string \n'.rstrip('\n')
'test string '
#更通用的做法,系统相关
>>> import os, sys
>>> sys.platform
'linux2'
>>> "foo\r\n".rstrip(os.linesep)
'foo\r'
python中字符串的contains
问题 链接
python中字符串判断contains
使用in关键字
if not "blah" in somestring: continue
if "blah" not in somestring: continue
使用字符串的find/index (注意index查找失败抛异常)
s = "This be a string"
if s.find("is") == -1:
print "No 'is' here!"
else:
print "Found 'is' in the string."
如何判断一个字符串是数字
问题 链接
使用这种方法会不会十分丑陋和低效
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
使用这种方法并不丑陋和低效
使用isdigit(缺点,对非整数无能为力)
a = "03523"
a.isdigit()
如何填充0到数字字符串中保证统一长度
问题 链接
对于字符串
>>> n = '4'
>>> print n.zfill(3)
>>> '004'
对于数字,相关文档
>>> n = 4
>>> print '%03d' % n
>>> 004
>>> print "{0:03d}".format(4) # python >= 2.6
>>> 004
>>> print("{0:03d}".format(4)) # python 3
>>> 004
控制结构(条件、循环)
如何在循环中获取下标
问题 链接
使用enumerate
for idx, val in enumerate(ints):
print idx, val
如何判断一个变量的类型
问题 链接
使用type
>>> i = 123
>>> type(i)
<type 'int'>
>>> type(i) is int
True
>>> i = 123456789L
>>> type(i)
<type 'long'>
>>> type(i) is long
True
>>> i = 123.456
>>> type(i)
<type 'float'>
>>> type(i) is float
True
另外一个相同的问题 链接
>>> type( [] ) == list
True
>>> type( {} ) == dict
True
>>> type( "" ) == str
True
>>> type( 0 ) == int
True
>>> class Test1 ( object ):
pass
>>> class Test2 ( Test1 ):
pass
>>> a = Test1()
>>> b = Test2()
>>> type( a ) == Test1
True
>>> type( b ) == Test2
True
>>> type( b ) == Test1
False
>>> isinstance( b, Test1 )
True
>>> isinstance( b, Test2 )
True
>>> isinstance( a, Test1 )
True
>>> isinstance( a, Test2 )
False
>>> isinstance( [], list )
True
>>> isinstance( {}, dict )
True
类
如何判断一个对象是否拥有某个属性
问题 链接
if hasattr(a, 'property'):
a.property
两种风格
EAFP(easier to ask for forgiveness than permission)
LBYL(look before you leap)
相关内容 EAFP vs LBYL (was Re: A little disappointed so far) EAFP vs. LBYL @Code Like a Pythonista: Idiomatic Python
try:
doStuff(a.property)
except AttributeError:
otherStuff()
or
if hasattr(a, 'property'):
doStuff(a.property)
else:
otherStuff()
Python中的类变量(环境变量)
问题 链接
在类中定义的变量,不在方法定义中,成为类变量或静态变量
>>> class MyClass:
... i = 3
...
>>> MyClass.i
3
i是类级别的变量,但这里要和实例级别的变量i区分开
>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)
这和C++/java完全不同,但和C#区别不大,C#不允许类实例获取静态变量
具体见 what the Python tutorial has to say on the subject of classes and class objects
另外,静态方法
class C:
@staticmethod
def f(arg1, arg2, ...): ...
如何定义静态方法(static method)
问题 链接
使用 staticmethod装饰器
class MyClass(object):
@staticmethod
def the_static_method(x):
print x
MyClass.the_static_method(2) # outputs 2
@staticmethod和@classmethod的区别
问题 链接
staticmethod,静态方法在调用时,对类及实例一无所知
仅仅是获取传递过来的参数,没有隐含的第一个参数,在Python里基本上用处不大,你完全可以用一个模块函数替换它
classmethod, 在调用时,将会获取到其所在的类,或者类实例,作为其第一个参数
当你想将函数作为一个类工厂时,这非常有用: 第一个参数是类,你可以实例化出对应实例对象,甚至子类对象。
可以观察下 dict.fromkey(),是一个类方法,当子类调用时,返回子类的实例
>>> class DictSubclass(dict):
... def __repr__(self):
... return "DictSubclass"
...
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>>
如何获取一个实例的类名
问题 链接
x.__class__.__name__
模块
如何列出一个目录的所有文件
问题 链接
1.使用os.listdir(),得到目录下的所有文件和文件夹
#只需要文件
from os import listdir
from os.path import isfile, join
onlyfiles = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ]
2.os.walk()
from os import walk
f = []
for (dirpath, dirnames, filenames) in walk(mypath):
f.extend(filenames)
break
3.glob
import glob
print glob.glob("/home/adam/*.txt")
重复问题 链接
import os
for dirname, dirnames, filenames in os.walk('.'):
# print path to all subdirectories first.
for subdirname in dirnames:
print os.path.join(dirname, subdirname)
# print path to all filenames.
for filename in filenames:
print os.path.join(dirname, filename)
json和simplejson的区别
问题 链接
json就是simple,加入到标准库. json在2.6加入,simplejson在2.4+,2.6+,更有优势
另外,simplejson更新频率更高,如果你想使用最新版本,建议用simplejson
好的做法是
try: import simplejson as json
except ImportError: import json
另外,可以关注二者性能上的比较
python中如何获取当前时间
问题 链接
时间日期
>>> import datetime
>>> datetime.datetime.now()
datetime(2009, 1, 6, 15, 8, 24, 78915)
如果仅获取时间
>>> datetime.datetime.time(datetime.datetime.now())
datetime.time(15, 8, 24, 78915))
#等价
>>> datetime.datetime.now().time()
可以从文档中获取更多 文档
如果想避免额外的datetime.
>>> from datetime import datetime
其他
如何从标准输入读取内容stdin
问题 链接
import fileinput
for line in fileinput.input():
pass
foo is None 和 foo == None的区别
问题 链接
if foo is None: pass
if foo == None: pass
如果比较相同的对象实例,is总是返回True 而 == 最终取决于 “eq()”
>>> class foo(object):
def __eq__(self, other):
return True
>>> f = foo()
>>> f == None
True
>>> f is None
False
>>> list1 = [1, 2, 3]
>>> list2 = [1, 2, 3]]
>>> list1==list2
True
>>> list1 is list2
False
另外
(ob1 is ob2) 等价于 (id(ob1) == id(ob2))
__init__.py是做什么用的
问题 链接
这是包的一部分,具体文档
__init__.py让Python把目录当成包,
最简单的例子,__init__.py仅是一个空文件,但它可以一样执行包初始化代码或者设置__all__变量,后续说明
如何获取安装的python模块列表
问题 链接
>>> help('modules')
环境相关
setup.py安装后如何卸载
问题 链接
使用下面命令安装的包如何卸载
python setup.py install
手工删除的话
python setup.py install --record files.txt
cat files.txt | xargs rm -rf
异常
如何一行内处理多个异常
问题 链接
我知道可以这么做
try:
# do something that may fail
except:
# do this if ANYTHING goes wrong
也可以
try:
# do something that may fail
except IDontLikeYourFaceException:
# put on makeup or smile
except YouAreTooShortException:
# stand on a ladder
如果想在一行里处理多个异常的话
try:
# do something that may fail
except IDontLIkeYouException, YouAreBeingMeanException: #没生效
except Exception, e: #捕获了所有
# say please
答案
# as在python2.6,python2.7中仍然可以使用
except (IDontLIkeYouException, YouAreBeingMeanException) as e:
pass
如何flush Python的print输出
默认print输出到sys.stdout
import sys
sys.stdout.flush()
参考 http://docs.python.org/reference/simple_stmts.html#the-print-statement http://docs.python.org/library/sys.html http://docs.python.org/library/stdtypes.html#file-objects
如何获取一个函数的函数名字符串
问题 链接
my_function.__name__
>>> import time
>>> time.time.__name__
'time'
应该在学习Python3之前学习Python2,还是直接学习Python3
问题 链接
你可以从python2开始,2和3主要的语法格式和风格相同
3要替代2不是短时间内能完成的,将会是一个很长的过程,所以学习Python2并没有什么坏处
我建议你关注下2和3的不同之处 This slides gives you a quick introduction of the changes in Python 2 and 3
python中用==比较字符串,is有时候会返回错误判断
问题 链接
is是身份测试,==是相等测试
>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False'
is 等价于 id(a) == id(b)
如何截取一个字符串获得子串
问题 链接
>>> x = "Hello World!"
>>> x[2:]
'llo World!'
>>> x[:2]
'He'
>>> x[:-2]
'Hello Worl'
>>> x[-2:]
'd!'
>>> x[2:-2]
'llo Worl'
python将这类操作称为切片,可以作用于序列类型,不仅仅是字符串
用函数名字符串调用一个函数
问题 链接
假设模块foo有函数bar:
import foo
methodToCall = getattr(foo, 'bar')
result = methodToCall()
或者一行搞定
result = getattr(foo, 'bar')()
如何获取文件扩展名
问题 链接
使用os.path.splitext方法:
>>> import os
>>> fileName, fileExtension = os.path.splitext('/path/to/somefile.ext')
>>> fileName
'/path/to/somefile'
>>> fileExtension
'.ext'
如何获取list中包含某个元素所在的下标
问题 链接
>>> ["foo","bar","baz"].index('bar')
1
参照 文档
如何截掉空格(包括tab)
问题 链接
空白在字符串左右两边
s = " \t a string example\t "
s = s.strip()
空白在字符串右边
s = s.rstrip()
左边
s = s.lstrip()
另外你可以指定要截掉的字符作为参数
s = s.strip(' \t\n\r')
如何将一个十六进制字符串转为整数
问题 链接
>>> int("a", 16)
10
>>> int("0xa",16)
10
如何结束退出一个python脚本
问题 链接
import sys
sys.exit()
详细 文档
如何往文件中追加文本
问题 链接
with open("test.txt", "a") as myfile:
myfile.write("appended text")
可以使用’a’或’a+b’ mode打开文件,见 文档
如何使用不同分隔符切分字符串
问题 链接
使用re.split 文档
>>> re.split('\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split('(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split('\W+', 'Words, words, words.', 1)
['Words', 'words, words.'])
或者匹配获取正确的 re.findall
import re
DATA = "Hey, you - what are you doing here!?"
print re.findall(r"[\w']+", DATA)
# Prints ['Hey', 'you', 'what', 'are', 'you', 'doing', 'here']
如何获取一个字符的ASCII码
问题 链接
>>> ord('a')
97
>>> chr(97)
'a'
>>> chr(ord('a') + 3)
'd'
>>>
另外对于unicode
>>> unichr(97)
u'a'
>>> unichr(1234)
u'\u04d2'
排序一个列表中的所有dict,根据dict内值
问题 链接
如何排序如下列表,根据name或age
[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
简单的做法;
newlist = sorted(list_to_be_sorted, key=lambda k: k['name'])
高效的做法
from operator import itemgetter
newlist = sorted(list_to_be_sorted, key=itemgetter('name'))
读文件到列表中
问题 链接
f = open('filename')
lines = f.readlines()
f.close()
等价
with open(fname) as f:
content = f.readlines()
如何用http下载一个文件
问题 链接
直接使用urllib
import urllib
urllib.urlretrieve ("http://www.example.com/songs/mp3.mp3", "mp3.mp3")
使用urllib2,并提供一个进度条
import urllib2
url = "http://download.thinkbroadband.com/10MB.zip"
file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print "Downloading: %s Bytes: %s" % (file_name, file_size)
file_size_dl = 0
block_sz = 8192
while True:
buffer = u.read(block_sz)
if not buffer:
break
file_size_dl += len(buffer)
f.write(buffer)
status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
status = status + chr(8)*(len(status)+1)
print status,
f.close()
使用第三方requests包
>>> import requests
>>>
>>> url = "http://download.thinkbroadband.com/10MB.zip"
>>> r = requests.get(url)
>>> print len(r.content)
10485760
在virtualenv中如何使用不同的python版本
问题 链接
在创建virtualenv实例时,使用-p选项
virtualenv -p /usr/bin/python2.6 <path/to/new/virtualenv/>
python中如何将一行长代码切成多行
问题 链接
例如:
e = 'a' + 'b' + 'c' + 'd'
变成
e = 'a' + 'b' +
'c' + 'd'
括号中,可以直接换行
a = dostuff(blahblah1, blahblah2, blahblah3, blahblah4, blahblah5,
blahblah6, blahblah7)
非括号你可以这么做
a = '1' + '2' + '3' + \
'4' + '5'
或者
a = ('1' + '2' + '3' +
'4' + '5')
可以查看下代码风格: style guide 推荐是后一种,但某些个别情况下,加入括号会导致错误
如何找到一个目录下所有.txt文件
问题 链接
使用glob
import glob
import os
os.chdir("/mydir")
for files in glob.glob("*.txt"):
print files
使用os.listdir
import os
os.chdir("/mydir")
for files in os.listdir("."):
if files.endswith(".txt"):
print files
或者遍历目录
import os
for r,d,f in os.walk("/mydir"):
for files in f:
if files.endswith(".txt"):
print os.path.join(r,files)
如何使用绝对路径import一个模块
问题 链接
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
如何在遍历一个list时删除某些玄素
问题 链接
使用列表解析
somelist = [x for x in somelist if determine(x)]
上面那个操作将产生一个全新的somelist对象,而失去了对原有somelist对象的引用
#在原有对象上进行修改
somelist[:] = [x for x in somelist if determine(x)]
使用itertools
from itertools import ifilterfalse
somelist[:] = list(ifilterfalse(determine, somelist))
如何强制使用浮点数除法
问题 链接
如何强制使除法结果c是浮点数
c = a / b
可以使用__future__
>>> from __future__ import division
>>> a = 4
>>> b = 6
>>> c = a / b
>>> c
0.66666666666666663
或者转换,如果除数或被除数是浮点数,那么结果也是浮点数
c = a / float(b)
如何映射两个列表成为一个字典
问题 链接
两个列表
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
如何得到
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
使用zip
>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print dictionary
{'a': 1, 'b': 2, 'c': 3}
找到当前目录及文件所在目录
问题 链接
查找当前目录使用os.getcwd()
查找某个文件的目录,使用, os.path
import os.path
os.path.realpath(__file__)
为何1 in [1,0] == True执行结果是False
问题 链接
有如下
>>> 1 in [1,0] # This is expected
True
>>> 1 in [1,0] == True # This is strange
False
>>> (1 in [1,0]) == True # This is what I wanted it to be
True
>>> 1 in ([1,0] == True) # But it's not just a precedence issue!
# It did not raise an exception on the second example.
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
1 in ([1,0] == True)
TypeError: argument of type 'bool' is not iterable
这里python使用了比较运算符链
1 in [1,0] == True
将被转为
(1 in [1, 0]) and ([1, 0] == True)
很显然是false的
同样的
a < b < c
会被转为
(a < b) and (b < c) # b不会被解析两次
Python中的switch替代语法
问题 链接
python中没有switch,有什么推荐的处理方法么
使用字典:
def f(x):
return {
'a': 1,
'b': 2,
}.get(x, 9)
Python Cookbook中的几种方式
Readable switch construction without lambdas or dictionaries
Using a Dictionary in place of a ‘switch’ statement
如何将字符串转换为datetime
问题 链接
可以查看下time模块的strptime方法,反向操作是strftime
from datetime import datetime
date_object = datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')
Python中有没有简单优雅的方式定义单例类
问题 链接
我不认为有必要,一个拥有函数的模块(不是类)可以作为很好的单例使用,它的所有变量被绑定到这个模块,无论如何都不能被重复实例化
如果你确实想用一个类来实现,在python中不能创建私有类或私有构造函数,所以你不能隔离多个实例而仅仅通过自己的API来访问属性
我还是认为将函数放入模块,并将其作为一个单例来使用是最好的办法
将一个字符串转为一个字典
问题 链接
如何将字符串转成字典,不适用eval
s = "{'muffin' : 'lolz', 'foo' : 'kitty'}"
从python2.6开始,你可以使用内建模块 ast.literal_eval
>>> import ast
>>> ast.literal_eval("{'muffin' : 'lolz', 'foo' : 'kitty'}")
{'muffin': 'lolz', 'foo': 'kitty'}
这个做法比直接eval更安全 帮助文档
>>> help(ast.literal_eval)
Help on function literal_eval in module ast:
literal_eval(node_or_string)
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the following
Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
and None.
举例
>>> eval("shutil.rmtree('mongo')")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 208, in rmtree
onerror(os.listdir, path, sys.exc_info())
File "/opt/Python-2.6.1/lib/python2.6/shutil.py", line 206, in rmtree
names = os.listdir(path)
OSError: [Errno 2] No such file or directory: 'mongo'
>>> ast.literal_eval("shutil.rmtree('mongo')")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 68, in literal_eval
return _convert(node_or_string)
File "/opt/Python-2.6.1/lib/python2.6/ast.py", line 67, in _convert
raise ValueError('malformed string')
ValueError: malformed string
Python如何检查一个对象是list或者tuple,但是不是一个字符串
问题 链接
原来的做法是
assert isinstance(lst, (list, tuple))
有没有更好的做法
我认为下面的方式是你需要的
assert not isinstance(lst, basestring)
原来的方式,你可能会漏过很多像列表,但并非list/tuple的
使用 ‘if x is not None’ 还是’if not x is None’
问题 链接
我总想着使用 ‘if x is not None’ 会更加简明
但是google的Python风格指南使用的却是 ‘if x is not None’
性能上没有什么区别,他们编译成相同的字节码
Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39)
>>> import dis
>>> def f(x):
... return x is not None
...
>>> dis.dis(f)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 0 (None)
6 COMPARE_OP 9 (is not)
9 RETURN_VALUE
>>> def g(x):
... return not x is None
...
>>> dis.dis(g)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 0 (None)
6 COMPARE_OP 9 (is not)
9 RETURN_VALUE
在风格上,我尽量避免 ’not x is y’ 这种形式,虽然编译器会认为和 ’not (x is y)‘一样,但是读代码的人或许会误解为 ‘(not x) is y’
如果写作 ‘x is not y’ 就不会有歧义
最佳实践
if x is not None:
# Do something about x
如何获取一个文件的创建和修改时间
问题 链接
跨平台的获取文件创建及修改时间的方法
你有很多选择
使用os.path.getmtime或者os.path.getctime
import os.path, time
print "last modified: %s" % time.ctime(os.path.getmtime(file))
print "created: %s" % time.ctime(os.path.getctime(file))
或者os.stat
import os, time
(mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(file)
print "last modified: %s" % time.ctime(mtime)
注意,ctime()并非指*nix系统中文件创建时间,而是这个节点数据的最后修改时间
如何离开virtualenv
问题 链接
使用virtualenv时
me@mymachine:~$ workon env1
(env1)me@mymachine:~$ workon env2
(env2)me@mymachine:~$ workon env1
(env1)me@mymachine:~$
如何退出某个环境
$ deactivate
如何认为地抛出一个异常
问题 链接
pythonic
raise Exception("I know python!")
更多可参考 文档
在Python中如何展示二进制字面值
问题 链接
十六进制可以
>>> 0x12AF
4783
>>> 0x100
256
八进制可以
>>> 01267
695
>>> 0100
64
二进制如何表示?
Python 2.5 及更早版本: 可以表示为 int(‘01010101111’,2) 但没有字面量
Python 2.6 beta: 可以使用0b1100111 or 0B1100111 表示
Python 2.6 beta: 也可以使用 0o27 or 0O27 (第二字字符是字母 O)
Python 3.0 beta: 同2.6,但不支持027这种语法
Python中检查类型的权威方法
问题 链接
检查一个对象是否是给定类型或者对象是否继承于给定类型?
比如给定一个对象o,如何判断是不是一个str
检查是否是str
type(o) is str
检查是否是str或者str的子类
isinstance(o, str)
下面的方法在某些情况下有用
issubclass(type(o), str)
type(o) in ([str] + str.__subclasses__())
注意,你或许想要的是
isinstance(o, basestring)
因为unicode字符串可以满足判定(unicode 不是str的子类,但是str和unicode都是basestring的子类)
可选的,isinstance可以接收多个类型参数,只要满足其中一个即True
isinstance(o, (str, unicode))
如何获取Python的site-packages目录位置
问题 链接
参考 How to Install Django" documentation
可以在shell中执行
python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"
更好的可读性
from distutils.sysconfig import get_python_lib
print(get_python_lib())
Python中**和*的作用
问题 链接
*args和**kwargs允许函数拥有任意数量的参数,具体可以查看 more on defining functions
*args将函数所有参数转为序列
In [1]: def foo(*args):
...: for a in args:
...: print a
...:
...:
In [2]: foo(1)
1
In [4]: foo(1,2,3)
1
2
3
**kwargs 将函数所有关键字参数转为一个字典
In [5]: def bar(**kwargs):
...: for a in kwargs:
...: print a, kwargs[a]
...:
...:
In [6]: bar(name="one", age=27)
age 27
name one
两种用法可以组合使用
def foo(kind, *args, **kwargs):
pass
*l的另一个用法是用于函数调用时的参数列表解包(unpack)
In [9]: def foo(bar, lee):
...: print bar, lee
...:
...:
In [10]: l = [1,2]
In [11]: foo(*l)
1 2
在Python3.0中,可以将*l放在等号左边用于赋值 Extended Iterable Unpacking
first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]
字符串格式化 % vs format
问题 链接
Python2.6中引入string.format()方法,语法和原先%操作符的字符串格式化差异较大
在什么情况下使用哪种更好?
以下的输出是一致的,有什么区别
#!/usr/bin/python
sub1 = "python string!"
sub2 = "an arg"
a = "i am a %s"%sub1
b = "i am a {0}".format(sub1)
c = "with %(kwarg)s!"%{'kwarg':sub2}
d = "with {kwarg}!".format(kwarg=sub2)
print a
print b
print c
print d
.format 看起来更加强大,可以用在很多情况.
例如你可以在格式化时重用传入的参数,而你用%时无法做到这点
另一个比较讨厌的是,%只处理 一个变量或一个元组, 你或许会认为下面的语法是正确的
"hi there %s" % name
但当name恰好是(1,2,3)时,会抛出TypeError异常.为了保证总是正确的,你必须这么写
"hi there %s" % (name,) # supply the single argument as a single-item tuple
这么写很丑陋, .format没有这些问题
什么时候不考虑使用.format
你对.format知之甚少
使用Python2.5
Python中什么项目结构更好
问题 链接
假设你要开发一个较大的客户端程序(非web端),如何组织项目目录和递归?
不要太在意这个.按你高兴的方式组织就行.Python项目很简单,所以没有那么多愚蠢的规则
/scripts or /bin 命令行脚本
/tests 测试
/lib C-语言包
/doc 文档
/apidoc api文档
并且顶层目录包含README和Config
难以抉择的是,是否使用/src树. /src,/lib,/bin在Python中没有明显的区别,和Java/c不同
因为顶层/src文件夹显得没有什么实际意义,你的顶层目录可以是程序顶层架构的目录
/foo
/bar
/baz
我建议将这些文件放入到"模块名"的目录中,这样,如果你在写一个应用叫做quux, /quux目录将包含所有这些东西
你可以在PYTHONPATH中加入 /path/to/quux/foo,这样你可以QUUX.foo中重用模块
另一个回答
Project/
|-- bin/
| |-- project
|
|-- project/
| |-- test/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- setup.py
|-- README
argparse可选位置参数
问题 链接
脚本运行 usage: installer.py dir [-h] [-v]
dir是一个位置参数,定义如下
parser.add_argument('dir', default=os.getcwd())
我想让dir变为可选,如果未设置,使用os.getcwd()
不幸的是,当我不指定dir时,得到错误 “Error: Too few arguments”
尝试使用 nargs=’?’
parser.add_argument('dir', nargs='?', default=os.getcwd())
例子
>>> import os, argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-v', action='store_true')
_StoreTrueAction(option_strings=['-v'], dest='v', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('dir', nargs='?', default=os.getcwd())
_StoreAction(option_strings=[], dest='dir', nargs='?', const=None, default='/home/vinay', type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('somedir -v'.split())
Namespace(dir='somedir', v=True)
>>> parser.parse_args('-v'.split())
Namespace(dir='/home/vinay', v=True)
>>> parser.parse_args(''.split())
Namespace(dir='/home/vinay', v=False)
>>> parser.parse_args(['somedir'])
Namespace(dir='somedir', v=False)
>>> parser.parse_args('somedir -h -v'.split())
usage: [-h] [-v] [dir]
positional arguments:
dir
optional arguments:
-h, --help show this help message and exit
-v
Python中 new 和 __init__的用法
问题 链接
我很疑惑,为何__init__总是在__new__之后调用
如下
class A(object):
_dict = dict()
def __new__(cls):
if 'key' in A._dict:
print "EXISTS"
return A._dict['key']
else:
print "NEW"
return super(A, cls).__new__(cls)
def __init__(self):
print "INIT"
A._dict['key'] = self
print ""
a1 = A()
a2 = A()
a3 = A()
输出
NEW
INIT
EXISTS
INIT
EXISTS
INIT
有木有人可以解释一下
来自 链接
使用__new__,当你需要控制一个实例的生成
使用__init__,当你需要控制一个实例的初始化
__new__是实例创建的第一步.最先被调用,并且负责返回类的一个新实例.
相反的,__init__不返回任何东西,只是负责在实例创建后进行初始化
通常情况下,你不必重写__new__除非你写一个子类继承不可变类型,例如str,int,unicode或tuple
你必须了解到,你尝试去做的用Factory可以很好地解决,并且是最好的解决方式.使用__new__不是一个简洁的处理方式,一个factory例子
Python ‘self’ 解释
问题 链接
self关键字的作用是什么? 我理解他用户在创建class时具体化实例,但我无法理解为何需要给每个方法加入self作为参数.
举例,在ruby中,我这么做:
class myClass
def myFunc(name)
@name = name
end
end
我可以很好地理解,非常简单.但是在Python中,我需要去加入self:
class myClass:
def myFunc(self, name):
self.name = name
有谁能解释下么?
使用self关键字的原因是,Python没有@语法用于引用实例属性.Python决定用一种方式声明方法:实例对象自动传递给属于它的方法,但不是接收自动化:方法的第一个参数是调用这个方法的实例对象本身.这使得方法整个同函数一致,并且由你自己决定真实的名(虽然self是约定,但当你使用其他名的时候,通常人们并不乐意接受).self对于代码不是特殊的,只是另一个对象.
Python本来可以做一些用来区分真实的名字和属性的区别 —— 像Ruby有的特殊语法,或者像C++/Java的命令声明,或者其他可能的的语法 —— 但是Python没有这么做.Python致力于使事情变得明确简单,让事情是其本身,虽然并不是全部地方都这么做,但是实例属性石这么做的!这就是为什么给一个实例属性赋值时需要知道是给哪个实例赋值,并且,这就是为什么需要self
举例
class Vector(object):
def __init__(self, x, y):
self.x = x
self.y = y
def length(self):
return math.sqrt(self.x ** 2 + self.y ** 2)
等价于
def length_global(vector):
return math.sqrt(vector.x ** 2 + vector.y ** 2)
另外
v_instance.length()
转为
Vector.length(v_instance)
为什么Python的’private’方法并不是真正的私有方法
问题 链接
Python允许我们创建’private’ 函数:变量以两个下划线开头,像这样: __myPrivateMethod(). 但是,如何解释:
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "", line 1, in
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
dir(obj) 和 obj._MyClass__myPrivateMethod()
回答
‘private’只是用作,确保子类不会意外覆写父类的私有方法和属性.不是为了保护外部意外访问而设计的!
例如:
>>> class Foo(object):
... def __init__(self):
... self.__baz = 42
... def foo(self):
... print self.__baz
...
>>> class Bar(Foo):
... def __init__(self):
... super(Bar, self).__init__()
... self.__baz = 21
... def bar(self):
... print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}
当然,这对于两个同名的类没有作用
另外,可以查看diveintopython的解释 入口
Python中类方法的作用是什么
问题 链接
我现在意识到,我不需要像我在使用java的static方法那样使用类方法,但是我不确定什么时候使用
谁能通过一个好的例子解释下Python中的类方法,至少有人能告诉我什么时候确实需要使用类方法
类方法用在:当你需要使用不属于任何明确实例的方法,但同时必须涉及类.有趣的是,你可以在子类中覆写,这在Java的static方法和Python的模块级别函数中是不可能做到的
如果你有一个MyClass, 并且一个模块级别函数操作MyClass(工厂,依赖注入桩等等), 声明一个类方法.然后这个类方法可以在子类中调用
如何删除一个list中重复的值同时保证原有顺序
问题 链接
我是这么做的额
def uniq(input):
output = []
for x in input:
if x not in output:
output.append(x)
return output
有什么更好的方法?
你可以在这里找到一些可用的方法 入口
最快的一个
def f7(seq):
seen = set()
seen_add = seen.add
return [ x for x in seq if x not in seen and not seen_add(x)]
如果你需要在同一个数据集中多次是哦那个这个方法,或许你可以使用ordered set处理 http://code.activestate.com/recipes/528878/
插入,删除和归属判断复杂度都是O(1)
有什么方法可以获取系统当前用户名么?
问题 链接
至少在Linux和Windows下都可用.就像 os.getuid
>>> os.getuid()
42
>>> os.getusername()
'slartibartfast'
可以看看 getpass 模块
>>> import getpass
>>> getpass.getuser()
'kostya'
可用: Unix, Windows
Python assert最佳实践
问题 链接
有没有代码实例使用assert作为独立代码,而不是仅用来debug
assert x >= 0, 'x is less than zero'
类似
if x < 0:
raise Exception, 'x is less than zero'
有什么方法,可以设定一个规则就像 if x \< 0 抛出错误但是不是通过try/except/finally检查的
搞晕了:
原文 Also, is there any way to set a business rule like if x \< 0 raise error that is always checked without the try/except/finally so, if at anytime throughout the code x is less than 0 an error is raised, like if you set assert x < 0 at the start of a function, anywhere within the function where x becomes less then 0 an exception is raised?
回答
Assert仅用在,测试那些从不发生的情况!目的是让程序尽早失败
Exception用在,那些可以明确知道会发生的错误,并且建议总是创建自己的异常类
例如,你写一个函数从配置文件中读取配置放入字典,文件格式不正确抛出一个ConfigurationSyntaxError,同时你可以assert返回值非None
在你的例子中,如果x是通过用户接口或外部传递设置的,最好使用exception
如果x仅是同一个程序的内部代码,使用assert
在非创建全局变量的地方使用全局变量
问题 链接
如果我在一个函数中创建了全局变量,如何在另一个函数中使用?
回答:
你可以在给全局变量赋值的函数中声明 global
globvar = 0
def set_globvar_to_one():
global globvar # Needed to modify global copy of globvar
globvar = 1
def print_globvar():
print globvar # No need for global declaration to read value of globvar
set_globvar_to_one()
print_globvar() # Prints 1
我猜想这么做的原因是,全局变量很危险,Python想要确保你真的知道你要对一个全局的变量进行操作
如果你想知道如何在模块间使用全局变量,查看其他回答
如何在单一表达式中合并两个Python字典
问题 链接
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = x.update(y)
>>> print z
None
>>> x
{'a': 1, 'b': 10, 'c': 11}
我想要最终合并结果在z中,不是x,我要怎么做?
回答
这种情况下,可以使用
z = dict(x.items() + y.items())
这个表达式将会实现你想要的,最终结果z,并且相同key的值,将会是y中key对应的值
>>> x = {'a':1, 'b': 2}
>>> y = {'b':10, 'c': 11}
>>> z = dict(x.items() + y.items())
>>> z
{'a': 1, 'c': 11, 'b': 10}
如果在Python3中,会变得有些复杂
>>> z = dict(list(x.items()) + list(y.items()))
>>> z
{'a': 1, 'c': 11, 'b': 10}
如何使用 pip 更新所有包
问题 链接
如何使用pip更新python的所有包
没有内置的标志可以实现
但是你可以这么做
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs pip install -U
Python中声明exception的方法
问题 链接
在python2.6中定义异常得到警告
>>> class MyError(Exception):
... def __init__(self, message):
... self.message = message
...
>>> MyError("foo")
_sandbox.py:3: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
问题很长,大意如标题
回答
或许我理解错了,但是为什么不这样做
class MyException(Exception):
pass
如果要重写什么,例如传递额外参数,可以这么做
class ValidationError(Exception):
def __init__(self, message, Errors):
# Call the base class constructor with the parameters it needs
Exception.__init__(self, message)
# Now for your custom code...
self.Errors = Errors
你可以通过第二个参数传递error 字典, 之后通过e.Errors获取
在Python中使用Counter错误
问题 链接
当使用Counter时,出现异常
AttributeError: 'module' object has no attribute 'Counter'
from collections import Counter
ImportError: cannot import name Counter
原因:
版本问题,Counter在 python2.7中才被加入到这个模块,你可能使用了Python2.6或更老的版本
可以看下 文档
如果要在 Python2.6或2.5版本使用,可以看 这里
如何删除Python easy_install安装的包
问题 链接
pip, setuptools/easy_install的另一种选择,提供uninstall命令
首先,移除依赖
$ easy_install -m [PACKAGE]
然后,手动删除egg文件
$ rm -rf .../python2.X/site-packages/[PACKAGE].egg
在Python中如何解析xml
问题 链接
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>
如何解析获取xml文件中内容
我建议使用 ElementTree (有其他可用的实现,例如 lxml,他们只是更快, ElementTree提供更简单的编程api)
在使用XML建立Element实例之后,例如使用 XML 函数
for atype in e.findall('type')
print(atype.get('foobar'))
如何将一个Python time.struct_time对象转换为一个datetime对象
问题 链接
使用 time.mktime() 将time元组(本地时间)转成秒, 然后使用 datetime.fromtimestamp() 转成datetime对象
from time import mktime
from datetime import datetime
dt = datetime.fromtimestamp(mktime(struct))