对多个变量设置相同的值时,用连等号一起赋值

x = 10
y = 10
z = 10

改成:

x = y = z = 10

交换变量值时,可以避免定义新的临时变量

x = 10
y = 5 temp = x
x = y
y = temp

改成:

x = 10
y = 5 x, y = y, x

多次调用字符对象方法时,可以用链式调用方法,避免中间产生过多变量  

str1 = 'i am a bug!'
str2 = str1.strip()
str3 = str2.upper()
str4 = str3.replace('!', '?')

改成:

str4 = str1.strip().upper().replace('!', '?')

当然,如果连续调用链过长,也会使代码不清楚,作者给的建议是最好不要超过三次调用

拼接字符列表时,用join方法去实现

mylist = ['i', 'am', 'a', 'bug']
resultStr = ''
for e in mylist:
resultStr += e

改成:

mylist = ['i', 'am', 'a', 'bug']
resultStr = ''.join(mylist)

  

格式化字符时多使用format函数

我们格式化字符时一般会用下面两种方式:

name = "tony"
age = 100
str = "myname : " + name + " my age : " + str(age) str1 = "myname : %s my age : %d" % (name, age)

改成:

str2 = "myname : {} my age {}".format(name, age)

对list对象进行相关操作并生成新的对象时多使用comprehension(这个怎么翻译?)

mylist = range(20)

odd_list = []
for e in mylist:
if e % 2 == 1:
odd_list.append(e)

改成:

mylist = range(20)
odd_list = [e for e in mylist if e % 2 == 1]

这种写法性能更好

有时候使用负列表索引更方便

mylist = range(20)

len_mylist = len(mylist)
last_five_list = mylist[len_mylist - 5:]

改成:

last_five_list = mylist[-5:]

判断一个列表里的元素是否都为True时,可以对列表进行all操作

def contains_zero(itor):
for e in itor:
if e:
return False
return True

改成:

def contains_zero(itor):
return all(itor)

all只有在列表中的每个元素都返回True时才会返回True

区别xrange和range

range会在内存中生成完整的列表实例, 而xrange则只是生成一个迭代器;

如下我只想打印一个集合中第一个偶数

for index in range(3, 1000000000):
if index % 2 == 0:
print index
break

在我机器上会出现如下错误,就是因为range会在内存中生成完整对象实例:

Traceback (most recent call last):
File "C:\Users\tony\Desktop\huawei.py", line 3, in <module>
for index in range(3, 1000000000):
MemoryError
[Finished in 0.2s with exit code 1]

改成如下就正常了:

for index in xrange(3, 1000000000):
if index % 2 == 0:
print index
break

用dict对象完成switch...case...的功能

在python里没有switch...case...功能。但是dict可以编写出更直观简洁的代码出来。如下,模拟一个计算器的功能,根据传入的操作符和操作数来算出结果:

def apply_operation(left_operand, right_operand, operator):
if operator == '+':
return left_operand + right_operand
elif operator == '-':
return left_operand - right_operand
elif operator == '*':
return left_operand * right_operand
elif operator == '/':
return left_operand / right_operand

改成:

def apply_operation(left_operand, right_operand, operator):
import operator as op
operator_mapper = {'+': op.add, '-': op.sub, '*': op.mul, '/': op.truediv}
return operator_mapper[operator](left_operand, right_operand)

使用dict.get方法可以提供一个默认值

我们在获取dict的某个元素时,因为不确定该键是否存在,所以一般是先检查,再获取。如下:

mydict = {'a': 1}

default_b = 2
if 'b' in mydict:
default_b = mydict['b'] print default_b

改成:

print mydict.get('b', 2)

大家或许只知道list的comprehension,其实dict也有comprehension

user_list = [{'name': 'lucy', 'email': 'lucy@g.com'}, {'name': 'lily', 'email': 'lily@g.com'}]

user_email = {}

for user in user_list:
if 'email' in user:
user_email[user['name']] = user['email']

改成:

{user['name']: user['email'] for user in user_list if 'email' in user}

    

利用set的集合运算功能

在很多场景中,我们经常要从两个集合(列表)中找出相同的,相异的,或者相互排除的元素列表,这个时候我们可以利用set本身支持的各种集合运算功能。就像数学中讲的集合的:相交,相并,异合等等。

如下我们要计算出满足两个特殊的相交集:

def get_both_popular_and_active_users():
most_popular_users = get_list_of_most_popular_users()
most_active_users = get_list_of_most_active_users()
popular_and_active_users = []
for user in most_active_users:
if user in most_popular_users:
popular_and_active_users.append(user)

改成:

def get_both_popular_and_active_users():
return(set(get_list_of_most_active_users()) & set(get_list_of_most_popular_users()))

set支持的运算有: A & B, A | B, A ^ B 。还有一点要注意的,set在计算的时候如何判定两个元素相等的呢,除了要在类中定义的__eq__方法返回值相同外,还要定义 __hash__ 值相同。这点和java中的HashMap的判定行为(equals, hashCode)差不多

set的comprehension

到这里我们可以比较下list, dict, set 三种数据结构的comprehension的不同表述。list用[...], dict用{key:value...}, 而set用{...}

users_first_names = set()
for user in users:
users_first_names.add(user.first_name)

改成:

users_first_names = {user.first_name for user in users}

访问tuple的数据项时,可以用namedtuple代替index的方式访问

rows = [('lily', 20, 2000), ('lucy', 19, 2500)]

for row in rows:
print '{}`age is {}, salary is {} '.format(row[0], row[1], row[2])

改成:

Employee = namedtuple('Employee', 'name, age, salary')

for row in rows:
employee = Employee._make(row)
print '{}`age is {}, salary is {} '.format(employee.name, employee.age, employee.salary)

namedtuple方法会成一个tuple的子类,并通过类方法_make可以把一个tuple实例转换成一个可以通过name来索引的对象。这比通过index的方式更直观

作用isinstance来判断对象的类型

因为在python中定义变量时,不用像其它静态语言,如java, 要指定其变量数据类型,如int = 4. 但是这并不意味在python中没有数据类型,只是一个变量的数据类型是在运行的时候根据具体的赋值才最终确定。比如下面的代码是计算一个对象的长度值,如果是序列类型(str,list,set,dict)的, 直接调用len方法,如果是True, False, None则返回1,如果是数值的,则返回其int值.

def get_size(some_object):
try:
return len(some_object)
except TypeError:
if some_object in (True, False, None):
return 1
else:
return int(some_object) print(get_size('hello'))
print(get_size([1, 2, 3, 4, 5]))
print(get_size(10.0))

改成:

def get_size(some_object):
if isinstance(some_object, (list, dict, str, tuple)):
return len(some_object)
elif isinstance(some_object, (bool, type(None))):
return 1
elif isinstance(some_object, (int, float)):
return int(some_object)

这里有一点要注意,在判断对象是否是None时,用了type(None)。因为没有直接书面的形式表达None的类型。

在类中定义私有属性(private attribute)时,尽量用下划线开头的名称规范,如__name, _name

在python在,默认情况下所有的类属性,方法函数都默认是公共的(public),即外部对象可以访问。然后在有些情况下,我们需要约定一些成员属性或者方法只是内部使用,不能直接被外部修改。在python中达到这些的目的一般是通过“约定规范”来完成。比如某一个类属性以下划线(_)开头,则是显式的的约定该成员是具有私有属性的,最好不要在外部直接调用。当然这样的约定并不能阻止你这样做,但是良好素质的程序员应该都会遵守这个规定。而双下划线(__)开头的成员更具有“私有”的属性,因为在外部不能直接调用,因为python解译器把这些的成员名称进行变形处理,使外部不能轻易直接访问。来看下面一段代码:

class A(object):
__i = 1 def __init__(self):
self._j = 2 def printJ(self):
return self._j class B(A):
def __init__(self):
super(B, self).__init__()
self._j = 3 b = B()
print b.printJ() # 打印如下
3
[Finished in 0.3s]

我们发现类B的实例b调用printJ方法时输出3, 这是因为B的构造器中重写了self._j的赋值。假始我们现在就是希望printJ方法打印父类A的构造器中的self_j值,即打印2,修改代码如下:

class A(object):
__i = 1 def __init__(self):
self.__j = 2 def printJ(self):
return self.__j class B(A):
def __init__(self):
super(B, self).__init__()
self.__j = 3 b = B()
print b.printJ()

用__j 代替 _j, 这样B中就不能访问父类A中的私有变量__j,所以现在不是重写,而是重新定义了一个成员属性。可以通过下面的语句可以看出来确实是两个成员属性:

print b._A__j, b._B__j
#打印
2 3
[Finished in 0.3s]

 在class中定义__str__方法,这些在打印对象字符时更直观,更好阅读些

class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y p = Point(10, 11)
print p

打印结果:

<__main__.Point object at 0x7f2f0f6b5c50>

如果在程序中记录这些的日志往往是无有多少可用信息可用,因为我们更多的关注对象中的各成员实际值,所以可以重新定义__str__方法来覆盖默认的行为:

class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y def __str__(self):
return '{self.x},{self.y}'.format(self = self) p = Point(10, 11)
print p

打印:

10,11

就像java里重写toString方法一样

用with管理操作资源的上下文环境

在一个比较典型的场景里,如数据库操作,我们操作connection时一般要正常关闭连接,而不管是正常退出还是异常退出。如下:

class Connection(object):
def execute(self, sql):
raise Exception('ohoh, exception!') def close(self):
print 'closed the Connection' try:
conn = Connection()
conn.execute('select * from t_users')
finally:
conn.close()

上面我们用finally来保证conn的关闭。但是我们可以用with更优雅的完成这个工作。

class Connection(object):
def execute(self, sql):
raise Exception('ohoh, exception!') def close(self):
print 'closed the Connection' def __enter__(self):
return self def __exit__(self, errorType, errorValue, error):
self.close() with Connection() as conn:
conn.execute('select * from t_users')

注意: 用with管理资源时,要定义__enter__和__exit__方法,它们分别在进入with和退出上下文时执行

运用generator

我们知道,运用list comprehensive可以对集合进行一定的运算变成另外一个集合对象,但是它会一下子生成所有元素并插入到新生成的列表集合中。如:

for e in [i * 2 for i in oneList]:
pass

但是这样会比较消耗资源,而我们的目的的只是遍历新生成的列表集合进行相应的运算,所以这个时候用generator更适合:

for e in (i * 2 for i in oneList):
pass

用(...) 代替 [....],就像用xrange代替range一样

分享书籍[writing idiomatic python ebook] 二的更多相关文章

  1. 分享书籍[writing idiomatic python ebook]

    你是不是总是觉得学了python好久,蓦然回首,总是感觉写的代码不是那么有pythonic的味道.看看别人的代码(django,webpy),再看看自己的代码,觉得就是一java-python的混合体 ...

  2. 翻译《Writing Idiomatic Python》(二):函数、异常

    原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...

  3. 《Writing Idiomatic Python》前两部分的中文翻译

    汇总了一下这本小书前两部分的内容: 翻译<Writing Idiomatic Python>(一):if语句.for循环 翻译<Writing Idiomatic Python> ...

  4. 翻译《Writing Idiomatic Python》(三):变量、字符串、列表

    原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...

  5. 翻译《Writing Idiomatic Python》(一):if语句、for循环

    开篇废话 这是在美国Amazon上评价很不错的一本书,其实严格来说这可能不算书,而是一本小册子.就像书名一样,里面的内容主要是用一些例子讲述地道的Python的代码是怎样写的.书中把很多例子用不良风格 ...

  6. 翻译《Writing Idiomatic Python》(五):类、上下文管理器、生成器

    原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...

  7. 翻译《Writing Idiomatic Python》(四):字典、集合、元组

    原书参考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/ 上一篇:翻译<Writing Idiomatic ...

  8. Python 基础 二

    Python 基础 二 今天对昨天学习的Python基础知识进行总结,学而不思则惘,思而不学则殆! 一.先对昨天学习的三大循环的使用情况进行总结: 1.while循环的本质就是让计算机在满足某一条件的 ...

  9. 初学Python(二)——数组

    初学Python(二)——数组 初学Python,主要整理一些学习到的知识点,这次是数组. # -*- coding:utf-8 -*- list = [2.0,3.0,4.0] #计算list长度 ...

随机推荐

  1. iOS segue 跳转

    场景描述: 要实现在tableViewController 的界面A里,点击一个cell ,跳转到第二个viewController的界面B .在第二个界面里做相应操作. 我的做法,利用sb,在A 里 ...

  2. linux查看时间和修改时间

    查看当前时间,date -R 设置时间 date -s 例如当前时间2014年11月3日17:22:48 date -s 11/3/2014 date -s 17:22:48 先设置日期后设置具体时间 ...

  3. 将request.getParameterMap()转换成可操作的普通Map

    在java web项目中虽然可以通过request.getParameterMap()很轻松的获得参数Map,但得到的Map和普通Map是不一样的,是被锁定的,不能像操作常规Map那样进行put.ge ...

  4. Bungie Interview with Halo3 Developer

    http://www.realtimerendering.com/blog/tag/bungie/ Digital Foundry interview with Halo: Reach develop ...

  5. 程序设计第二次作业<1>

    面向对象程序设计第二次作业<1> Github 链接:https://github.com/Wasdns/object-oriented 题目: <1>第一次尝试 我立马认识到 ...

  6. extjs4 树列表 添加子节点 刷新所有父节点数据

    itemclick:function(view, record, item,index){console.log(record.parentNode) for(pNode = record.paren ...

  7. Android系统用于Activity的标准Intent

    1 根据联系人ID显示联系人信息 Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW);   //显示联系人信息 int ...

  8. mysql storage enginees

    这段时间在看<High Performance MySQL>,看到存储引擎这个地方感到很多细节比较陌生,所以总结小记一些 为 了适应各种不同的运行环境,MYSQL提供了多种不同的存储引擎( ...

  9. Qt持久性对象进行序列化

    Mfc和Java中自定义类的对象都可以对其进行持久性保存,Qt持久性对象进行序列化当然也是必不可少的.不过这个问题还真困扰了我很长时间……Mfc通过重写虚函数Serialize().Java则是所属的 ...

  10. JavaSE的知识

    一 SE的知识体系: java基础: 一基础语法 8个基本数据类型-->8个包装类 数据类型转换: 自动转换(从小到大) 强制转换(从大到小) 注意:int 和char 分支与判断: if(){ ...