Python Specification: improve readability

PEP 8 specification

PEP is an acronym for Python Enhancement Proposal, the translation is called "Python enhanced specification."

Indent specification

  PEP 8 specifications tell us, please choose indented four spaces, do not use the Tab, Tab, and not to use mixed with spaces. The second thing to note is that the maximum length of each line is limited to 79 characters, please.

Blank line specification

  PEP 8 provides the above classes and functions required global empty two blank lines, and the class of functions between the blank requires a blank line.

Space specifications

Function's parameter list, the parameter list will appear in the calling function comma, please pay attention to keep a space after the comma, which is the English usage, but also allows each parameter independent reading and clearer.

  • Also keep a space after the colon.
  • After the # before the comment by a space.
  • Operators, such as +, -, *, /, &, |!, =, ==, =, please have reserved spaces around. But to this, the two ends in brackets do not need the space.

Wrap Specification

  Control the maximum length of each line is not more than 79 characters, but sometimes, function calls in the following specifications logic is too long and had to exceed this figure when:

def solve1(this_is_the_first_parameter, this_is_the_second_parameter, this_is_the_third_parameter,
           this_is_the_forth_parameter, this_is_the_fifth_parameter, this_is_the_sixth_parameter):
    return (this_is_the_first_parameter + this_is_the_second_parameter + this_is_the_third_parameter +
            this_is_the_forth_parameter + this_is_the_fifth_parameter + this_is_the_sixth_parameter)


def solve2(this_is_the_first_parameter, this_is_the_second_parameter, this_is_the_third_parameter,
           this_is_the_forth_parameter, this_is_the_fifth_parameter, this_is_the_sixth_parameter):
    return this_is_the_first_parameter + this_is_the_second_parameter + this_is_the_third_parameter + \
           this_is_the_forth_parameter + this_is_the_fifth_parameter + this_is_the_sixth_parameter


(top_secret_func(param1=12345678, param2=12345678, param3=12345678, param4=12345678, param5=12345678).check()
    .launch_nuclear_missile().wait())


top_secret_func(param1=12345678, param2=12345678, param3=12345678, param4=12345678, param5=12345678).check() \
    .launch_nuclear_missile().wait()

  1. The long operation to be encapsulated by parentheses.

  2. achieved by line breaks.

Document specification

  • import as much as possible at the beginning.
  • Do not use the import module to import more.
  • Such a statement from module import func, func make sure that naming conflicts do not appear in this document. Or to rename from module import func as new_func carried out, thus avoiding collisions.

Notes Specification

Line comments is not very recommended way.

Document Description

docstring wording, it marks the beginning and end with the three pairs, three pairs of marks. We first sentence brief description of what the function does, and then with some words to explain in detail; and then again a list of parameters, parameter format, return value format.

class SpatialDropout2D(Dropout):
    """Spatial 2D version of Dropout.
    This version performs the same function as Dropout, however it drops
    entire 2D feature maps instead of individual elements. If adjacent pixels
    within feature maps are strongly correlated (as is normally the case in
    early convolution layers) then regular dropout will not regularize the
    activations and will otherwise just result in an effective learning rate
    decrease. In this case, SpatialDropout2D will help promote independence
    between feature maps and should be used instead.
    Arguments:
        rate: float between 0 and 1. Fraction of the input units to drop.
        data_format: 'channels_first' or 'channels_last'.
            In 'channels_first' mode, the channels dimension
            (the depth) is at index 1,
            in 'channels_last' mode is it at index 3.
            It defaults to the `image_data_format` value found in your
            Keras config file at `~/.keras/keras.json`.
            If you never set it, then it will be "channels_last".
    Input shape:
        4D tensor with shape:
        `(samples, channels, rows, cols)` if data_format='channels_first'
        or 4D tensor with shape:
        `(samples, rows, cols, channels)` if data_format='channels_last'.
    Output shape:
        Same as input
    References:
        - [Efficient Object Localization Using Convolutional
          Networks](https://arxiv.org/abs/1411.4280)
  """
    def __init__(self, rate, data_format=None, **kwargs):
        super(SpatialDropout2D, self).__init__(rate, **kwargs)
        if data_format is None:
            data_format = K.image_data_format()
        if data_format not in {'channels_last', 'channels_first'}:
            raise ValueError('data_format must be in '
                           '{"channels_last", "channels_first"}')
        self.data_format = data_format
        self.input_spec = InputSpec(ndim=4)

Naming conventions

Variable use lower case, underlined by series, for example: data_format, input_spec, image_data_set. The only place you can use a single character is iterative, such as for i in range (n) that, in order to streamline can be used. If the class private variables, please remember to add two underscore in front.

  • Constant, the best practice is all caps, and connected by an underscore, for example: WAIT_TIME, SERVER_ADDRESS, PORT_NUMBER.
  • Function name, also use the lowercase mode, connected by an underscore, for example: launch_nuclear_missile (), check_input_validation ().
  • Class name should be capitalized, then combined, for example: class SpatialDropout2D (), class FeatureSet ().

Code decomposition techniques

Do not write duplicate code.

Such as:

if i_am_rich:
    money = 100
    send(money)
else:
    money = 10
    send(money)

Has a send function can be changed to:

if i_am_rich:
    money = 100
else:
    money = 10
send(money)

Code deeply nested:

def send(money):
    if is_server_dead:
        LOG('server dead')
        return
    else:
        if is_server_timed_out:
            LOG('server timed out')
            return
        else:
            result = get_result_from_server()
            if result == MONEY_IS_NOT_ENOUGH:
                LOG('you do not have enough money')
                return
            else:
                if result == TRANSACTION_SUCCEED:
                    LOG('OK')
                    return
                else:
                    LOG('something wrong')
                    return

  Can be changed to:

def send(money):
    if is_server_dead:
        LOG('server dead')
        return

    if is_server_timed_out:
        LOG('server timed out')
        return

    result = get_result_from_server()

    if result == MONET_IS_NOT_ENOUGH:
        LOG('you do not have enough money')
        return

    if result == TRANSACTION_SUCCEED:
        LOG('OK')
        return

    LOG('something wrong')

  In a simple binary search exemplified. Given a non-decreasing array of integers and a target, the minimum required to find an array of a number x, satisfy x * x> target. Once absent, -1 is returned.

  If the code is implemented as shown below, and then to a function you can only do one thing at the principle of re-optimization.

def solve(arr, target):
    l, r = 0, len(arr) - 1
    ret = -1
    while l <= r:
        m = (l + r) // 2
        if arr[m] * arr[m] > target:
            ret = m
            r = m - 1
        else:
            l = m + 1
    if ret == -1:
        return -1
    else:
        return arr[ret]


print(solve([1, 2, 3, 4, 5, 6], 8))
print(solve([1, 2, 3, 4, 5, 6], 9))
print(solve([1, 2, 3, 4, 5, 6], 0))
print(solve([1, 2, 3, 4, 5, 6], 40))

  Optimization as follows:

def comp(x, target):
    return x * x > target


def binary_search(arr, target):
    l, r = 0, len(arr) - 1
    ret = -1
    while l <= r:
        m = (l + r) // 2
        if comp(arr[m], target):
            ret = m
            r = m - 1
        else:
            l = m + 1
    return ret


def solve(arr, target):
    id = binary_search(arr, target)

    if id != -1:
        return arr[id]
    return -1


print(solve([1, 2, 3, 4, 5, 6], 8))
print(solve([1, 2, 3, 4, 5, 6], 9))
print(solve([1, 2, 3, 4, 5, 6], 0))
print(solve([1, 2, 3, 4, 5, 6], 40))

  Class attributes can be extracted as a class alone many of the same characteristics, such as:

class Person:
    def __init__(self, name, sex, age, job_title, job_description, company_name):
        self.name = name
        self.sex = sex
        self.age = age
        self.job_title = job_title
        self.job_description = description
        self.company_name = company_name

  job_title, job_description, company_name are work-related, the expression is the same sense entity, it can be extracted as a separate category:

class Person:
    def __init__(self, name, sex, age, job_title, job_description, company_name):
        self.name = name
        self.sex = sex
        self.age = age
        self.job = Job(job_title, job_description, company_name)

class Job:
    def __init__(self, job_title, job_description, company_name):
        
        self.job_title = job_title
        self.job_description = description
        self.company_name = company_name

Guess you like

Origin www.cnblogs.com/xxpythonxx/p/11599999.html