




























更新到github了,地址:https://github.com/wklken/stackoverflow-py-top-qa
后续这里不更新了哈
进度40%,最近有点犯懒
刚刚注册,好东西
查看了下前面(vote前15页,挑了下,vote都是100+的样子,大概120个)的问题,链接, 大体梳理了下,本来想放一页搞定,奈何排版太乱,按类型分了下
第一页的前几个比较长,目测都有中文翻译版本,大家可以网上搜下
其他问题相对比较杂,有些简单,有些复杂,拉过来参考参考也不错
总结整理,复习印证(注意,合并了每个问题的多个答案,但是时间仓促,疏漏难免,感兴趣问题直接点链接看原文吧)
问题 链接
答案:
if not a:
print "List is empty"
#不要用len(a)来判断
问题 链接
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__()方法的对象
问题 链接
可以用切片的方法
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)
问题 链接
>>> 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}
问题 链接
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.
问题 链接
有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是字符串
>>> 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))
读一个文件,如何获取每一行内容(不包括换行符)
比较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
使用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()
问题 链接
对于字符串
>>> 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()
问题 链接
在类中定义的变量,不在方法定义中,成为类变量或静态变量
>>> 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, ...): ...
问题 链接
使用 staticmethod装饰器
class MyClass(object):
@staticmethod
def the_static_method(x):
print x
MyClass.the_static_method(2) # outputs 2
问题 链接
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就是simple,加入到标准库. json在2.6加入,simplejson在2.4+,2.6+,更有优势
另外,simplejson更新频率更高,如果你想使用最新版本,建议用simplejson
好的做法是
try: import simplejson as json
except ImportError: import json
另外,可以关注二者性能上的比较
问题 链接
时间日期
>>> 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
问题 链接
import fileinput
for line in fileinput.input():
pass
问题 链接
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让Python把目录当成包,
最简单的例子,__init__.py仅是一个空文件,但它可以一样执行包初始化代码或者设置__all__变量,后续说明
问题 链接
>>> help('modules')
问题 链接
使用下面命令安装的包如何卸载
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
默认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'
问题 链接
你可以从python2开始,2和3主要的语法格式和风格相同
3要替代2不是短时间内能完成的,将会是一个很长的过程,所以学习Python2并没有什么坏处
我建议你关注下2和3的不同之处 This slides gives you a quick introduction of the changes in Python 2 and 3
问题 链接
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'
问题 链接
>>> ["foo","bar","baz"].index('bar')
1
参照 文档
问题 链接
空白在字符串左右两边
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
问题 链接
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']
问题 链接
>>> ord('a')
97
>>> chr(97)
'a'
>>> chr(ord('a') + 3)
'd'
>>>
另外对于unicode
>>> unichr(97)
u'a'
>>> unichr(1234)
u'\u04d2'
问题 链接
如何排序如下列表,根据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()
问题 链接
直接使用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实例时,使用-p选项
virtualenv -p /usr/bin/python2.6 <path/to/new/virtualenv/>
问题 链接
例如:
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 推荐是后一种,但某些个别情况下,加入括号会导致错误
问题 链接
使用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 imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
问题 链接
使用列表解析
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] # 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,有什么推荐的处理方法么
使用字典:
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
问题 链接
可以查看下time模块的strptime方法,反向操作是strftime
from datetime import datetime
date_object = datetime.strptime('Jun 1 2005 1:33PM', '%b %d %Y %I:%M%p')
问题 链接
我不认为有必要,一个拥有函数的模块(不是类)可以作为很好的单例使用,它的所有变量被绑定到这个模块,无论如何都不能被重复实例化
如果你确实想用一个类来实现,在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
问题 链接
原来的做法是
assert isinstance(lst, (list, tuple))
有没有更好的做法
我认为下面的方式是你需要的
assert not isinstance(lst, basestring)
原来的方式,你可能会漏过很多像列表,但并非list/tuple的
问题 链接
我总想着使用 ‘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时
me@mymachine:~$ workon env1
(env1)me@mymachine:~$ workon env2
(env2)me@mymachine:~$ workon env1
(env1)me@mymachine:~$
如何退出某个环境
$ deactivate
问题 链接
pythonic
raise Exception("I know 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这种语法
问题 链接
检查一个对象是否是给定类型或者对象是否继承于给定类型?
比如给定一个对象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))
问题 链接
参考 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())
问题 链接
*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]
问题 链接
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
问题 链接
假设你要开发一个较大的客户端程序(非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
问题 链接
脚本运行 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
问题 链接
我很疑惑,为何__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例子
问题 链接
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’ 函数:变量以两个下划线开头,像这样: __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的解释 入口
问题 链接
我现在意识到,我不需要像我在使用java的static方法那样使用类方法,但是我不确定什么时候使用
谁能通过一个好的例子解释下Python中的类方法,至少有人能告诉我什么时候确实需要使用类方法
类方法用在:当你需要使用不属于任何明确实例的方法,但同时必须涉及类.有趣的是,你可以在子类中覆写,这在Java的static方法和Python的模块级别函数中是不可能做到的
如果你有一个MyClass, 并且一个模块级别函数操作MyClass(工厂,依赖注入桩等等), 声明一个类方法.然后这个类方法可以在子类中调用
问题 链接
我是这么做的额
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
问题 链接
有没有代码实例使用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想要确保你真的知道你要对一个全局的变量进行操作
如果你想知道如何在模块间使用全局变量,查看其他回答
问题 链接
>>> 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更新python的所有包
没有内置的标志可以实现
但是你可以这么做
pip freeze --local | grep -v '^\-e' | cut -d = -f 1 | xargs pip install -U
问题 链接
在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获取
问题 链接
当使用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版本使用,可以看 这里
问题 链接
pip, setuptools/easy_install的另一种选择,提供uninstall命令
首先,移除依赖
$ easy_install -m [PACKAGE]
然后,手动删除egg文件
$ rm -rf .../python2.X/site-packages/[PACKAGE].egg
问题 链接
<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'))
问题 链接
使用 time.mktime() 将time元组(本地时间)转成秒, 然后使用 datetime.fromtimestamp() 转成datetime对象
from time import mktime
from datetime import datetime
dt = datetime.fromtimestamp(mktime(struct))
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。