当前位置:网站首页>Not a programmer, code can't be too ugly! The official writing standard of Python: pep8 everyone should know

Not a programmer, code can't be too ugly! The official writing standard of Python: pep8 everyone should know

2020-11-08 16:58:00 LHH

brief introduction : Why emphasize Writing norms ? It's not really about “ The beauty and ugliness ”, It's about Higher efficiency ( Code reading 、 Development 、 maintain ) With more convenient cooperation ( A global standard ) . Now , No matter what direction the students should carry out “ Write code ” This work , It is a pity , Many friends don't realize : cost 1 Hours to understand code writing standards , You can save yourself 100+ Hours of code time . The charm of code specifications is Really simplify the problem , We don't need to be standard or controversial . In this paper, we mainly use python For example , With pep8 For the main reference material , There are three levels of discussion .

There are three levels in this paper :

  • Don't pay attention to these , You're not writing code at all
  • These specifications , The essence is to respect the logic of the procedure
  • Some of the norms I'm going to ignore , More thinking

Don't pay attention to these , You're not writing code at all

1/2 Take a look at my code two years ago

import tkinter
import tkinter.messagebox
def message_box(error_content):
    top = tkinter.Tk()  # *********
    top.withdraw()  # **** Hide the main window 
    top.update()  # ********* need update once 
    txt=tkinter.messagebox.showinfo(" Tips ",error_content)
    top.destroy()
    return txt

The above is in use python Of tkinter Make a desktop app , It seems that there is no problem ? Big problem , For example, project logic / Design architecture It's really hard to see through these lines of code ; however , The writing habits of the above lines of code , It reflects that one's thinking is not mature enough :

  • Notes don't need # **** Write it like this , No need at all
  • need update once This is bullshit , The front is not update() Function? ?
  • (" Tips ",error_content) There should be a space in the middle
  • txt=tkinter There should be spaces on the left and right sides

If I were to write , I will implement the following :

import tkinter
from tkinter import messagebox as msg

def show_message_box(error_content):
    """
    Piper Egg nests :
     Input error message ,messagebox  display information 

    ( A skin : Welcome to your attention  Piper Egg nests ~)
    """
    tk = tkinter.Tk()
    tk.withdraw()
    tk.update()
    txt = msg.showinfo(" Tips ", error_content)
    tk.destroy()
    return txt

Above :

  • I've got rid of some minor problems , For example, whether there are spaces, etc , But that's not the point
  • I took the function name from message_box Change it to show_message_box , because message_box It looks like a noun , It's not a verb ( To carry out a task ), After the complexity of the project structure , We may have many functions 、 class 、 example , If Don't make a gerund distinction , We can all confuse ourselves with , Also turn back to the source code to check , Waste a lot of time
  • I annotate ( What does this function do ) On the """ notes """ in , This interpreter and InelliSense When we call , Make automatic instructions , Here's the picture

 Pictured , Intelligently display our comments when called

2/2 The most basic : Indent 、 Naming and space

friend , If you write code with Indent 、 Naming and space None of these things will be noticed , The congratulations , This article is likely to take you up a level .

I've just learned c Our freshman , In the computer room VC 6 Knock down the characters one by one :

#include <stdio.h>
int main()
{int a=5,b=7,c;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;}

Obviously , This kid's code is really just “ Typing characters into the computer ” nothing more ,ta I don't have the logic of the program 、 level . This code is dead , It's not living . I just add a few spaces and carriage returns , To explain , Why are these indentations 、 Naming and space make code real code .

#include <stdio.h>

int main()
{
    int a = 5, b = 7, c;
    printf("a = %d, b = %d, c = %d", a, b, c);
    return 0;
}

Above :

  • I put {} Independent , And indent the code block , Indicates that the code is a function main() Internal logic
  • I added spaces , If you put a=5 Turned into a = 5 , It's because programmers are people , You also need to read something clearly
  • I am here #include <stdio.h> And int main() There is a blank line in between , Because they are two things : The former is responsible for introducing io Standard library , The latter is responsible for executing logic . When writing code , Don't be stingy , To distinguish between different logic and tasks

Is the above discussion too basic ? Now let's python And its official documents pep 8 For example , Let's see more about the logic of the program 、 Official suggestions for code readability .

If someone shows you again next time ta Written “ Dead code ”, You throw this article to ta, Give Way ta Improve !

These specifications , The essence is to respect the logic of the procedure

1/4 Indents and spaces : Embody logic

Indentation Indent

A famous American play 《 Silicon valley 》 There's a plot in it , Programmers can make a lot of noise about using tabs or spaces , It seems to be a matter of principle ?

It's just a joke, of course .

stay python in , Recommended 4 Space to indent . I'm playing kdd cup Yes, I have 2 Space for indented ( official start toolkit in ). I think it doesn't matter , The key is , You have to unify it in the project .

Besides , Indentation is used to represent the structure of a program , If your structure is not inclusive , It's just line breaks , Then use it 4 A space indent would be stupid . as follows .

#  recommend 
foo = long_function_name(var_one, var_two,
                         var_three, var_four)
#  perhaps 
foo = long_function_name(var_one, var_two,
  var_three, var_four)
#  perhaps 
foo = long_function_name(var_one, var_two,
        var_three, var_four)
#  perhaps 
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)

#  stupid 
foo = long_function_name(var_one, var_two,
    var_three, var_four)
#  stupid 
def long_function_name(
    var_one, var_two, var_three,
    var_four):
    print(var_one)

Why? ? We use the bottom def long_function_name For example , Have you noticed :

  • print(var_one) Should be def long_function_name The internal structure of , So it has to be better than def long_function_name One more indent before
  • however var_one, var_two, var_three These parameters are def long_function_name Part of , And def long_function_name At the same level
  • The function parameters are aligned with the internal structure of the function , It's easy to confuse

therefore , You only need to Manufacturing differentiation Can . As for you, add two more spaces , Or two less , It doesn't matter ( Unless your organization has specific rules ), Let you and others see the logical structure at a glance .

Should a line break before or after a binary operator?

Besides , pep 8 And recommended operator The location of , I didn't really notice this before .

# No: operators sit far away from their operands
income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)

# Yes: easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

Besides , To prevent compilation errors , I'll add \\ To escape a newline key .

income = (gross_wages \
          + taxable_interest \
          + (dividends - qualified_dividends) \
          - ira_deduction \
          - student_loan_interest)

Now it seems , It may not be necessary in this case .

Reject meaningless spaces

Yes: spam(ham[1], {eggs: 2})
No:  spam( ham[ 1 ], { eggs: 2 } )

Yes: if x == 4: print x, y; x, y = y, x
No:  if x == 4 : print x , y ; x , y = y , x

Above is Pet Peeves Suggestions in , Obviously , Too loose structure , It's not good for us to read and see logic . It's a habit common to all programming languages , It's worth cultivating .

Missing values of function variables

# Yes
def complex(real, imag=0.0):
    return magic(r=real, i=imag)

# No
def complex(real, imag = 0.0):
    return magic(r = real, i = imag)

Above , When defining a missing value , We encourage the removal of = The space around .

# Yes
def munge(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...

# No
def munge(input: AnyStr=None): ...
def munge(input: AnyStr, limit = 1000): ...

however , Above , It is worth noting that , If you define the data type of the function ( Such as AnyStr), Then we need to remind developers to distinguish , Do not remove = The space around .

2/4 import

Yes: import os
     import sys

No:  import sys, os

# Yes
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y
c = (a+b) * (a-b)

# No
i=i+1
submitted +=1
x = x * 2 - 1
hypot2 = x * x + y * y
c = (a + b) * (a - b)

About import There are several specifications for , I would like to emphasize here that a novice might have “ bad habit ”: Put irrelevant libraries in a import Next .

What's the picture ? It doesn't make any sense . For example, above ,sys In fact, with os There is no inclusive relationship , Why should we be stingy in this business import Well ? And put them together , It's not good for formatter Help us organize our writing .

3/4 Variable 、 The name of the function

Choose a good naming rule

Different enterprises / organization , Especially large enterprises , There's going to be a naming convention of its own . about java , I think the most commonly used one should be “ hump ” It's named after :

public void printUserName(int index) {
    ...
}

stay python , Encourage various generic forms of naming , Such as :

  • printUserName
  • print_user_name

I think you're in python The most common one is Underline + A lowercase letter In the form of .

stay pep 8 Of Descriptive: Naming Styles There's a label , It's funny :

Capitalized_Words_With_Underscores (ugly!)

Why do you say Capitalized_Words_With_Underscores “ ugly ” Well ?

I think it is Information redundancy 了 : Underline or capital initial , They are used to space words , Both use , It's really not concise 、 Not elegant .

“ private ” Variable

stay C++ perhaps java in , We are all exposed to private This kind of concept . Beginners may be confused : Why do variables have to be private 、 Public 、 The protected ?

python Let the beginner avoid this part may produce the incomprehensibility , But it doesn't remove the functions such as private variables , I think it's just pythonic The embodiment of . and , Today's language has this trend , such as go , Limit initial case sensitive variables private common , Simple and elegant , It also unifies the norms of community development .

about python , We put two underscores before the variables , Then it becomes private . Private variables for the specification and security of the project , Cannot be called externally , I wrote a program as follows .

Above , Call directly Foo.__a perhaps foo.__b Will produce AttributeError error . however python To give a “ back door ”, You can still pass _ Class name __ Variable name Call private variables .

4/4 Respect “ The human mind ”

# Yes
if foo is not None:

# No
if not foo is None:

Above , Maybe the novice will feel not ... is This structural logic is reversed , It's fun , Although its function is similar to is not Exactly the same .

Or that sentence , Programmers are people , Everyone likes simple and clear logic . Unless it's a clever trick , otherwise , There's no need to play word games , Reduce efficiency .

# Yes
try:
    value = collection[key]
except KeyError:
    return key_not_found(key)
else:
    return handle_value(value)

# No
try:
    # Too broad!
    return handle_value(collection[key])
except KeyError:
    # Will also catch KeyError raised by handle_value()
    return key_not_found(key)

Above , In the use of try catch when , We want to capture KeyError , Then don't be in try Do other operations in . Why? ?

  • If handle_value() There's something wrong with it , So it's hard for us to pass handle_value(collection[key]) Catch their own mistakes , Because of its relationship with collection[key] Possible mistakes are mixed up
# Yes
def foo(x):
    if x >= 0:
        return math.sqrt(x)
    else:
        return None

def bar(x):
    if x < 0:
        return None
    return math.sqrt(x)

# No
def foo(x):
    if x >= 0:
        return math.sqrt(x)

def bar(x):
    if x < 0:
        return
    return math.sqrt(x)

Above , x Less than 0 when , Can't square , Naturally, you can't input math.sqrt() . Here we should make the program clearer , Although we know that if a function does nothing, it returns None , But don't forget to write return None . use pep 8 Saying , We should be be consistent in return statements.

Some of the norms I'm going to ignore , More thinking

1/3 Maximum number of characters per line ?I say NO.

We know , pep 8 I hope every line of us most 79 Characters .

I think for developers like me , It's really not necessary . and , I've read a lot of good open source frameworks , It doesn't respect that standard either .

The reason is simple , Our production environment is different .

I like big font , And I only have a little laptop , There's no station . Many friends have several screens / Lengthen the screen , And I can only split a small laptop monitor in two . Here's the picture .

Whether it's 79 Characters , still 109 Characters , My editor doesn't even show up in one line , So this code doesn't mean much to me .

Maybe develop python The standard library uses . But not now .

2/3 Note file standards ? I reconsider

pep 8 And pep 257 in , All of them have standardized the way of annotation , as follows .

def complex(real=0.0, imag=0.0):
    """Form a complex number.

    Keyword arguments:
    real -- the real part (default 0.0)
    imag -- the imaginary part (default 0.0)
    """
    if imag == 0.0 and real == 0.0:
        return complex_zero
    ...

I'm not very interested in . reason :

  • I remember pyCharm in , The default comment doesn't look like this , The specification standard is not the only one
  • What standard should be used , I feel like Take the matter on its merits , such as MkDocs Will help us automatically compile comments into documents and publish them online , So we want to use MkDocs when , To learn MkDocs That's good

Above is thu-ml/tianshou Source code , Its annotation uses markdown Written , If you go to the documentation , You'll find that documentation is automatically generated from source code comments .

Amazing. That's what it is. “ Code writing ” The virtue that ought to be : lazy , No repetition , If it can be automated .

3/3 It's better to read more good projects than to read standard documents

Last , Just say no fake tricks .

in my opinion , Read more good code 、 project , Consciously pay attention to the master's writing rules and how to arrange the project structure , It's much more meaningful than reading pep 8 It's much bigger. .

I wish you all better . Welcome to the official account :Piper Egg nests , reply WeChat Add me WeChat . welcome give the thumbs-up 、 Click on Looking at Encourage me .

版权声明
本文为[user-u zsXbv7Bi]所创,转载请带上原文链接,感谢