Effective Python2 读书笔记1

本文介绍了Python编程中的实用技巧,包括遵循PEP8风格指南、区分str和unicode类型、编写辅助函数代替复杂表达式等内容。

Item 2: Follow the PEP 8 Style Guide

Naming

Naming
functions, variables, attributeslowercase_underscore
protected instance attributes_leading_underscore
private instance attributes__double_leading_underscore
classes, exceptionsCapitalizedWord
module-level constantsALL_CAPS

 

 

 

 

 

 

 

 

 

 

 

Expressions and Statements

Always use absolute names for modules when importing them, not names relative to the current module's own path.

# not good
import foo
foo.bar()

# good
from foo import bar
bar()

 

Item 3: Know the Differences Between str and unicode

In Python2, there are two types that represent sequences of characters: str and unicode. Instances of str contain raw 8-bit values. Instances of unicode contain Unicode characters.

The most common encoding to represent Unicode characters as binary data is UTF-8. Unicode instance in Python 2 do not have an associated binary encoding. To convert Unicode characters to binary data, you must use the encode method. To convert binary data to Unicode characters, you must use the decode method.

The core of your program should use Unicode character type (unicode in Python 2) and should not assume anything about character encodings. This approach allows you to be very accepting of alternative text encoding while being strict about your output text encoding.

def to_unicode(unicode_or_str):
    if isinstance(unicode_or_str, str):
        value = unicode_or_str.decode('utf-8')
    else:
        value = unicode_or_str
    return value    # Instance of unicode

def to_str(unicode_or_str):
    if isinstance(unicode_or_str, unicode):
        value = unicode_or_str.encode('utf-8')
    else:
        value = unicode_or_str
    return value    # Instance of str

In Python 2, file operations default to binary encoding. But still always open file using a binary mode (like 'rb' or 'wb').

 

Item 4: Write Helper Functions Instead of Complex Expressions

Python's syntax makes it all too easy to write single-line expressions that are overly complicated and difficult to read.

Move complex expressions into helper functions, especially if you need to use the same logic repeatedlly.

The if/else expression provides a more readable alternative to using Boolean operators like or and and in expressions.

from urllib.parse import parse_qs
my_values = parse_qs('red=5&blue=0&green=',
                                  keep_blank_values=True)
print(repr(my_values))

>>>
{'red': ['5'], 'green': [''], 'blue': ['0']}

# just use get method
print('Red:        ', my_values.get('red'))
print('Green:     ', my_values.get('green'))
print('Opacity:   ', my_values.get('opacity'))

>>>
Red:         ['5']
Green:      ['']
Opacity:    None

# what about  set a default of 0, use or operator
red = int(my_values.get('red', [''])[0] or 0)
green = int(my_values.get('green', [''])[0] or 0)
opacity = int(my_values.get('opacity', [''])[0] or 0)

# use if/else expression
red = my_values.get('red')
red = int(red[0]) if red[0] else 0

# ues if/else statement
green = my_values.get('green')
if green[0]:
    green = int(green[0])
else:
    green = 0

# helper function, make sense
def get_first_int(values, key, default=0):
    found = values.get(key, [''])
    if found[0]:
        found = int(found[0])
    else:
        found = default
    return found

green = get_first_int(my_values, 'green')

 

Item 5: Know How to Slice Sequence

lst = [1, 2, 3]
first_twenty_items = lst[:20]
last_twenty_items = lst[-20:]

lst[20]

>>>
IndexError: list index out of range


from copy import copy, deepcopy

# lst[-0:] equal to copy(lst), same as lst[:]

lst = [1, 2, 3, [4, 5]]
a = copy(lst)
b = deepcopy(lst)

lst[-1].append(6)
lst.append(7)

print lst
print a
print b

>>>
[1, 2, 3, [4, 5, 6], 7]
[1, 2, 3, [4, 5, 6]]
[1, 2, 3, [4, 5]]


lst = [1, 2, 3, 4]
lst[1:] = [3]
print lst

>>>
[1, 3]

 

Item 6: Avoid Using start, end, and stride in a Single Slice

a = ['red', 'orange', 'yellow', 'green', 'blue', 'purple']
odds = a[::2]
evens = a[1::2]
print(odds)
print(evens)

>>>
['red', 'yellow', 'blue']
['orange', 'green', 'purple']


# reverse a byte string, but break for unicode
x = b'mongoose'
y = x[::-1]
print(y)

>>>
b'esoognom'


a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
a[::2]           # ['a', 'c', 'e', 'g']
a[::-2]          # ['h', 'f', 'd', 'b']
a[2::2]         # ['c', 'e', 'g']
a[-2::-2]      # ['g', 'e', 'c', 'a']
a[-2:2:-2]    # ['g', 'e']
a[2:2:-2]     # [] 

Specifying start, end, and stride in a slice can be extremely confusing. Avoid using them together in a single slice.

 

Item 7: Use List Comprehensions Instead of map and filter

a = [1,2,3,4,55,6,7,7,8,9]

# clear
even_squares = [x**2 for x in a if x % 2 == 0]

# sucks
alt = map(lambda x: x**2, filter(lambda x: x % 2 == 0, a))

assert even_squares == list(alt)

 

Item 8: Avoid More Than Two Expressions in List Comprehensions

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
print flat

>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]


squared = [[x**2 for x in row] for row in matrix]
print squared

>>>
[[1, 4, 9], [16, 25, 36], [49, 64, 81]]


my_lists = [
    [[1, 2, 3], [4, 5, 6]],
    #...
]

# not good
flat = [x for sublist1 in my_lists
          for sublist2 in sublist1
          for x in sublist2]

# clear
flat = []
for sublist1 in my_lists:
    for sublist2 in sublist1:
        flat.extend(sublist2)

List comprehensions with more than two expressions are very difficult to read and should be avoided.

 

Item 9: Consider Generator Expressions for Large Comprehensions

Generator expressions avoid memory issues by producing outputs one at a time as an iterator.

 

Item 10: Prefer enumerate Over range

flavor_list = ['vanilla', 'chocolate', 'pecan', 'strawberry']

# usually
for i in range(len(flavor_list)):
    flavor = flavor_list[i]
    print('%d: %s' % (i + 1, flavor))

# enumerate
for i, flavor in enumerate(flavor_list):
    print('%d: %s' % (i + 1, flavor))

# specify which enumerate should begin count
for i, flavor in enumerate(flavor_list, 1):
    print('%d: %s' % (i, flavor))

 

Item 11: Use zip to Process Iterators in Parallel

names = ['Cecilia', 'Lise', 'Marie']
letters = [len(n) for n in names]

# usually
longest_name = None
max_letters = 0

for i in range(len(names)):
    count = letters[i]
    if count > max_letters:
        longest_name = names[i]
        max_letters = count

print(longest_name)


# using enumerate
for i, name in enumerate(names):
    count = letters[i]
    if count > max_letters:
        longest_name = names[i]
        max_letters = count

# using zip
for name, count in zip(names, letters):
    if count > max_letters:
        longest_name = name
        max_letters = count

In Python 2, use izip from the itertools built-in module when zip very large iterators.

If the lengths tht lists you want to zip aren't equal, use izip_longest.

 

Item 12: Avoid else Blocks After for and while Loops

Just Avoid use it.

 

Item 13: Take Advantage of Each Block in try/except/else/finally

Else Blocks

When the try block doesn't raise an exception, the else block will run. The else block helps you minimize the amount of code in the try block and improves readability.

def load_json_key(data, key):
    try:
        result_dict = json.loads(data)    # May raise ValueError
    except ValueError as e:
        raise KeyError from e:
    else:
        return result_dict[key]    # May raise KeyError

The else clause ensure that what follows the try/except is visually distinguished from the except block. This makes the exception propagation behavior clear.

 

The try/finally compound statement lets you run cleanup code regardless of whether exceptions were raised in the try block.

The else block helps you minimize the amount of code in try blocks and visually distinguish the success case from the try/except blocks.

An else block can be used to perform additional actions after a successful try block but before common cleanup in a finally block.

 

转载于:https://www.cnblogs.com/senjougahara/p/5596069.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值