zoukankan      html  css  js  c++  java
  • Effective Python2 读书笔记1

    Item 2: Follow the PEP 8 Style Guide

    Naming

    Naming
    functions, variables, attributes lowercase_underscore
    protected instance attributes _leading_underscore
    private instance attributes __double_leading_underscore
    classes, exceptions CapitalizedWord
    module-level constants ALL_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.

  • 相关阅读:
    WPF 基础到企业应用系列1——开篇有益
    WPF 基础到企业应用系列2——WPF前世今生
    “云计算之旅”筹备完成,意见征询!
    31天重构学习笔记30. 尽快返回
    作为资深程序员,必定会掌握的十句谎话
    TaffyDB Writing queries
    TAFFY Working with data
    2012年全球最愚蠢的设计第一是微软,第二还是微软
    TaffyDB Introduction
    TaffyDB Beginner's Guide
  • 原文地址:https://www.cnblogs.com/senjougahara/p/5596069.html
Copyright © 2011-2022 走看看