Python編碼規(guī)范匯編_第1頁
Python編碼規(guī)范匯編_第2頁
Python編碼規(guī)范匯編_第3頁
Python編碼規(guī)范匯編_第4頁
Python編碼規(guī)范匯編_第5頁
已閱讀5頁,還剩46頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

Python編碼規(guī)范匯編前言:為了讓不同編碼習慣的開發(fā)者更好的協(xié)作配合,并且形成良好的基礎編碼規(guī)范與風格,我們以PEP8為基礎,修改了陳舊的規(guī)則,豐富了示例,并整理了工作中常見的不規(guī)范操作,最終形成此Python編碼規(guī)范與風格。一、編碼風格1.1縮進1.2每行最大長度1.3空白符1.4操作符1.5括號1.6空行1.7源文件編碼1.8Shebang1.9模塊引用(import)1.10模塊中的魔術變量(dunders)1.11注釋1.12文檔字符串1.13類型提示1.14字符串1.15文件和sockets1.16訪問控制1.17Main1.18命名二、編碼規(guī)范2.1三目運算符2.2None條件的判斷2.3lambda匿名函數(shù)2.4異常2.5條件表達式2.6True/False布爾運算2.7列表推導式2.8函數(shù)2.9變量工具與配置flake8pylintblackEditorConfig注意事項本規(guī)范適用于所有使用Python語言作為開發(fā)語言的軟件產品。由于Python2在2020年停止維護,建議新增的項目使用Python3.6+,可以使用到更多的高級特性。如果項目有兼容性需求需要支持老版本Python的,那么不涉及的特性可以忽略。本規(guī)范的示例采用符合Python3.6+的語法。必須(Mandatory):用戶必須采用;推薦(Preferable):用戶理應采用,但如有特殊情況,可以不采用;可選(Optional):用戶可參考,自行決定是否采用;未明確指明的則默認為

必須(Mandatory)。一、編碼風格規(guī)范地代碼布局有助于幫助開發(fā)者更容易地理解業(yè)務邏輯。1.1縮進1.1.1

【必須】

對于每級縮進,統(tǒng)一要求使用4個空格,而非tab鍵。pylint:bad-indentation.1.1.2

【必須】

續(xù)行,要求使用括號等定限界符,并且需要垂直對齊。正確示范#

與定界(括號)符對齊

foo

=

long_function_name(var_one,

var_two,

var_three,

var_four)

#

換行并增加4個額外的空格(一級縮進)

def

long_function_name(

var_one,

var_two,

var_three,

var_four):

print(var_one)

#

懸掛需要增加一級縮進

foo

=

long_function_name(

var_one,

var_two,

var_three,

var_four)錯誤示范

#

當不使用垂直對齊時,第一行不允許加參數(shù)

foo

=

long_function_name(var_one,

var_two,

var_three,

var_four)

#

下面這種情況,需要增加額外的縮進,否則無法區(qū)分代碼所在的縮進級別

def

long_function_name(

var_one,

var_two,

var_three,

var_four):

print(var_one)1.1.3

【推薦】

如果包含定界符(括號,中括號,大括號)的表達式跨越多行,那么定界符的擴回符,可以放置與最后一行的非空字符對齊或者與構造多行的開始第一個字符對齊。正確示范#

與最后一行的非空字符對齊

my_list

=

[

1,

2,

3,

4,

5,

6,

]

result

=

some_function_that_takes_arguments(

'a',

'b',

'c',

'd',

'e',

'f',

)

#

或者與開始構造多行的第一個字符對齊

my_list

=

[

1,

2,

3,

4,

5,

6,

]

result

=

some_function_that_takes_arguments(

'a',

'b',

'c',

'd',

'e',

'f',

)1.1.4

【推薦】

對于會經常改動的函數(shù)參數(shù)、列表、字典定義,建議每行一個元素,并且每行增加一個

,

。正確示范yes

=

('y',

'Y',

'yes',

'TRUE',

'True',

'true',

'On',

'on',

'1')

#

基本不再改變

kwlist

=

[

'False',

'None',

'True',

'and',

'as',

'assert',

...

'yield',

#

最后一個元素也增加一個逗號

,方便以后diff不顯示此行

]

person

=

{

'name':

'bob',

'age':

12,

#

可能經常增加字段

}錯誤示范#

關鍵字會不斷增加,每個元素都換行

kwlist

=

['False',

'None',

'True',

'and',

'as',

'assert',

'async',

...

]

person

=

{'name':

'bob',

'age':

12}1.1.5

【可選】

對于if判斷,一般來說盡量不要放置過多的判斷條件。換行時增加4個額外的空格。pycodestyle:E129visuallyindentedlinewithsameindentasnextlogicalline.備注:PEP8沒有明確規(guī)定,以下幾種都是允許的。建議使用前面2種方法,后2種會與已有的開源工具沖突。正確示范#

更推薦:在續(xù)行中,增加額外的縮進級別。允許and操作符在前

if

(this_is_one_thing

and

that_is_another_thing):

do_something()

#

更推薦:在續(xù)行中,增加額外的縮進級別

if

(this_is_one_thing

and

that_is_another_thing):

do_something()

#

允許:與定界符(括號)對齊,不需要額外的縮進

if

(this_is_one_thing

and

that_is_another_thing):

do_something()

#

允許:增加注釋,編輯器會提示語法高亮,有助于區(qū)分

if

(this_is_one_thing

and

that_is_another_thing):

#

Since

both

conditions

are

true,

we

can

frobnicate.

do_something()1.2每行最大長度1.2.1

【必須】

每行最多不超過

120

個字符。每行代碼最大長度限制的根本原因是過長的行會導致閱讀障礙,使得縮進失效。pylint:line-too-long.除了以下兩種情況例外:導入模塊語句。注釋中包含的URL。如果需要一個長的字符串,可以用括號實現(xiàn)隱形連接。正確示范x

=

('This

will

build

a

very

long

long

'

'long

long

long

long

long

long

string')1.3空白符1.3.1

【必須】

在表達式的賦值符號、操作符左右至少有一個空格。正確示范x

=

y

+

1錯誤示范x=y+1

x

=

y+11.3.2

【必須】

禁止行尾空白。pylint:trailing-whitespace.行尾空白雖然不會造成功能性異常,但是這些空白字符會被源碼管理系統(tǒng)標記出來顯示為差異,對開發(fā)人員造成困惱。正確示范#

YES:

尾部沒有空白符號

+

para

=

{}

+

para

=

{}

#

comment錯誤示范#

No:

結尾存在多余空白符號

-

para

=

{}?????

-

para

=

{}

#

comment??????1.4操作符1.4.1

【推薦】

Python沒有三目操作符,對于二目操作符來說,操作符允許在換行符之后出現(xiàn)。備注:pycodestyle工具與此條目相反,PEP8推薦操作符在這之前,更具備可讀性。PEP8:ShouldaLineBreakBeforeorAfteraBinaryOperator?。屏蔽pycodestyle:W503linebreakbeforebinaryoperator正確示范#

YES:

易于將運算符與操作數(shù)匹配,可讀性高

income

=

(gross_wages

+

taxable_interest

+

(dividends

-

qualified_dividends)

-

ira_deduction

-

student_loan_interest)錯誤示范#

No:

運算符的位置遠離其操作數(shù)

income

=

(gross_wages

+

taxable_interest

+

(dividends

-

qualified_dividends)

-

ira_deduction

-

student_loan_interest)1.5括號1.5.1

【必須】

tuple元組不允許逗號結尾,顯式增加括號規(guī)避。即使一個元素也加上括號。pylint:trailing-comma-tuple.行尾的逗號可能導致本來要定義一個簡單變量,結果變成tuple變量。正確示范trailingcomma

=

(['f'],)

return

(1,)錯誤示范trailingcomma

=

['f'],

#

tuple

return

1,1.6空行1.6.1

【必須】

模塊中的一級函數(shù)和類定義之間,需要空兩行。pycodestyle:E302expected2blanklines.1.6.2

【必須】

類中函數(shù)定義之間,空一行。pycodestyle:E302expected1blankline.1.6.3

【必須】

源文件須使用且僅使用

一個換行符

作為結尾。pylint:missing-final-newline,

trailing-newlines.1.6.4

【必須】

通常每個語句應該獨占一行。pylint:multiple-statements.如果測試結果與測試語句在一行放得下,你也可以將它們放在同一行。如果是

if

語句,只有在沒有

else

時才能這樣做。特別地,絕不要對

try/except

這樣做,因為

try

except

不能放在同一行。正確示范if

foo:

bar(foo)

else:

baz(foo)

try:

bar(foo)

except

ValueError:

baz(foo)錯誤示范if

foo:

bar(foo)

else:

baz(foo)

try:

bar(foo)

except

ValueError:

baz(foo)

try:

bar(foo)

except

ValueError:

baz(foo)1.6.5

【推薦】

可以在代碼段中的空一行來區(qū)分不同業(yè)務邏輯塊。"""This

is

the

example

module.

This

module

does

stuff.

"""

import

os

def

foo():

pass

class

MyClass():

def

__init__(self):

pass

def

foo(self):

pass

class

AnotherClass(object):

"""Another

class.

This

is

some

comments

for

another

class

"""

def

__init__(self,

a,

b):

if

a

>

b:

self._min

=

b

self._max

=

a

else:

self._min

=

a

self._max

=

b

self._gap

=

self._max

=

self._min

def

foo(self):

pass1.7源文件編碼1.7.1

【必須】

源文件編碼需統(tǒng)一使用

UTF-8

編碼,以下內容需要增加到每一個python文件的頭部。#

-*-

coding:

utf-8

-*-1.7.2

【必須】

**避免不同操作系統(tǒng)對文件換行處理的方式不同,一律使用

LF**。pylint:mixed-line-endings,

unexpected-line-ending-format.1.8Shebang1.8.1

【必須】

程序的main文件應該以

#!/usr/bin/envpython2

或者

#!/usr/bin/envpython3

開始,可以同時支持Python2、Python3的#!/usr/bin/envpython。非程序入口的文件不應該出現(xiàn)Shebang。正確示范#!/usr/bin/env

python3

#

-*-

coding:

utf-8

-*-

#1.9模塊引用(import)1.9.1

【必須】

每個導入應該獨占一行。pylint:multiple-imports.正確示范import

os

import

sys錯誤示范import

os,

sys1.9.2

【必須】

導入總應該放在文件頂部,位于模塊注釋和文檔字符串之后,模塊全局變量和常量之前。pylint:wrong-import-order.導入應該按照從最通用到最不通用的順序分組,每個分組之間,需要空一行:標準庫導入第三方庫導入本地導入每種分組中,建議每個模塊的完整包路徑按

字典序

排序,并忽略大小寫。正確示范import

foo

from

foo

import

bar

from

foo.bar

import

baz

from

foo.bar

import

Quux

from

Foob

import

ar1.9.3

【必須】

避免使用

from<module>import*,因為可能會造成命名空間的污染。pylint:wildcard-import.1.9.4

【必須】

禁止導入了模塊卻不使用它。pylint:unused-import.正確示范import

os

#

used

dir_path

=

os.path.abspath('.')錯誤示范import

os

#

unused

!

#

dir_path

=

os.path.abspath('.')1.10模塊中的魔術變量(dunders)1.10.1

【必須】

對于兩個

_

開頭和兩個

_

結尾的變量,如

__all__,__author__,__version__等,應該放在模塊文檔之后,其他模塊導入之前(__future__

除外)。1.10.2

【必須】

Python要求

future

導入必須出現(xiàn)在其他模塊導入之前。pylint:misplaced-future.正確示范#

-*-

coding:

utf-8

-*-

#

#

Copyright

@

2020

T

"""This

is

the

example

module.

This

module

does

stuff.

"""

from

__future__

import

barry_as_FLUFL

__all__

=

['a',

'b',

'c']

__version__

=

'0.1'

__author__

=

'Cardinal

Biggles'

import

os

import

sys1.11注釋有效的注釋有助于幫助開發(fā)者更快地理解代碼,模塊,函數(shù),方法,以及行內注釋的都有各自的風格。1.11.1

【必須】

所有#開頭的注釋,必須與所在的代碼塊同級,并置放在代碼之上。pycodestyle:E262inlinecommentshouldstartwith'#'.1.11.2

【必須】

注釋的每一行都應該以#和一個空格開頭。pycodestyle:E266toomanyleading'#'forblockcomment,

E262inlinecommentshouldstartwith'#'.1.11.3

【必須】

行內注釋#與代碼離開至少2個空格。pycodestyle:E261atleasttwospacesbeforeinlinecomment.1.11.4

【必須】

塊注釋:對于復雜的操作,可以在代碼之前寫若干行注釋,對簡單的代碼,可以放在行內。與代碼離開至少2個空格。正確示范#

this

is

a

very

complex

operation,

please

#

read

this

carefully

if

i

&

(i-1)

==

0:

#

do

my

job

...

#

單行注釋,為可讀性,至少離開代碼2個空格

x

=

x

+

1

#

Compensate

for

border1.11.5

【必須】

TODO注釋需要加上名字。TODO注釋應該在所有開頭處包含

TODO

字符串,緊跟著是用括號括起來的你的名字,email地址或其它標識符,然后是一個可選的冒號。接著必須有一行注釋,解釋要做什么。主要目的是為了有一個統(tǒng)一的TODO格式,這樣添加注釋的人就可以搜索到(并可以按需提供更多細節(jié))。寫了TODO注釋并不保證寫的人會親自解決問題。當你寫了一個TODO,請注上你的名字。為臨時代碼使用TODO注釋,它是一種短期解決方案。常見的IDE在提交代碼時,會檢查變更中包含了TODO并提醒開發(fā)者,防止提交是忘記還有未完成的代碼。如果TODO是將來做某事的形式,那么請確保包含一個指定的日期或者一個特定的事件(條件)。相同地,也可以留下

FIXME,

NOTES

注釋。正確示范#

TODO(zhangsan):

Change

this

to

use

relations.

#

FIXME(zhangsan@):

Please

fix

me

here.

#

NOTES(zhangsan):

This

is

some

notes.1.12文檔字符串Docstring文檔字符串提供了將文檔與Python模塊,函數(shù),類和方法相關聯(lián)的便捷方法。def

foobar():

"""Return

a

foobang

Optional

plotz

says

to

frobnicate

the

bizbaz

first.

"""PEP257全面描述了文檔字符串的風格。1.12.1

【推薦】

需對外發(fā)布的public模塊,函數(shù),類,方法等需要包含文檔字符串。內部使用的方法,函數(shù)等,要求使用簡單的注釋描述功能。pylint:missing-module-docstring,

missing-class-docstring,

missing-function-docstring.一個函數(shù)或方法,如果可以直接被其他開發(fā)者使用,需要提供文檔明確其含義,需要指出輸入,輸出,以及異常內容。1.12.2

【必須】

第一行應為文檔名,空一行后,輸入文檔描述。1.12.3

【推薦】

在使用文檔字符串時,推薦使用

reStructuredText

風格類型。正確示范def

fetch_bigtable_rows(big_table,

keys,

other_silly_variable=None):

"""Fetches

rows

from

a

Bigtable.

Retrieves

rows

pertaining

to

the

given

keys

from

the

Table

instance

represented

by

big_table.

Silly

things

may

happen

if

other_silly_variable

is

not

None.

:param

big_table:

An

open

Bigtable

Table

instance.

:param

keys:

A

sequence

of

strings

representing

the

key

of

each

table

row

to

fetch.

:param

other_silly_variable:

Another

optional

variable,

that

has

a

much

longer

name

than

the

other

args,

and

which

does

nothing.

:return:

A

dict

mapping

keys

to

the

corresponding

table

row

data

fetched.

Each

row

is

represented

as

a

tuple

of

strings.

For

example:

{'Serak':

('Rigel

VII',

'Preparer'),

'Zim':

('Irk',

'Invader'),

'Lrrr':

('Omicron

Persei

8',

'Emperor')}

If

a

key

from

the

keys

argument

is

missing

from

the

dictionary,

then

that

row

was

not

found

in

the

table.

:raises

ValueError:

if

`keys`

is

empty.

:raises

IOError:

An

error

occurred

accessing

the

bigtable.Table

object.

"""

pass1.12.4

【推薦】

類應該在其定義下有一個用于描述該類的文檔字符串。如果類有公共屬性(Attributes),那么文檔中應該有一個屬性(Attributes)段,并且應該遵守和函數(shù)參數(shù)相同的格式。正確示范class

SampleClass(object):

"""Summary

of

class

here.

Longer

class

information

Longer

class

information

:ivar

likes_spam:

A

boolean

indicating

if

we

like

SPAM

or

not.

:ivar

eggs:

An

integer

count

of

the

eggs

we

have

laid.

"""

def

__init__(self,

likes_spam=False):

"""Inits

SampleClass

with

blah."""

self.likes_spam

=

likes_spam

self.eggs

=

0

def

public_method(self):

"""Performs

operation

blah."""1.13類型提示Python是動態(tài)語言,在運行時無需指定變量類型。雖然運行時不會執(zhí)行函數(shù)與變量類型注解,但類型提示有助于閱讀代碼、重構、靜態(tài)代碼檢查與IDE的語法提示。推薦在項目中使用該特性。更多使用可以參考類型標注支持。類型提示示例代碼from

typing

import

List

class

Container(object):

def

__init__(self)

->

None:

self.elements:

List[int]

=

[]

def

append(self,

element:

int)

->

None:

self.elements.append(element)

def

greeting(name:

str)

->

str:

return

'Hello

'

+

name

#

變量定義

lang:

str

=

'zh'

success_code:

int

=

01.13.1

【必須】

模塊級變量,類和實例變量以及局部變量的注釋應在冒號后面有一個空格。pycodestyle:E231missingwhitespaceafter':'.1.13.2

【必須】

冒號前不應有空格。1.13.3

【必須】

如果有賦值符,則等號在兩邊應恰好有一個空格。pycodestyle:E225missingwhitespacearoundoperator.正確示范code:

int

=

10

class

Point(object):

coords:

Tuple[int,

int]

=

(0,

0)

label:

str

=

'<unknown>'

def

broadcast(servers:

Sequence[Server],

message:

str

=

'spaces

around

equality

sign')

->

None:

pass錯誤示范code:int

#

No

space

after

colon

code

:

int

#

Space

before

colon

class

Test(object):

result:

int=0

#

No

spaces

around

equality

sign1.13.4

【推薦】

當使用類型提示出現(xiàn)循環(huán)引用時,可以在導入的頭部使用

iftyping.TYPE_CHECKING

,且對類型注解使用雙引號或單引號進行修飾。正確示范import

typing

if

typing.TYPE_CHECKING:

#

運行時不導入

#

For

type

annotation

from

typing

import

Any,

Dict,

List,

Sequence

#

NOQA

from

sphinx.application

import

Sphinx

#

NOQA

class

Parser(docutils.parsers.Parser):

def

set_application(self,

app:

"Sphinx")

->

None:

#

同時采用引號

pass1.14字符串1.14.1

【推薦】

即使參數(shù)都是字符串,也要使用%操作符或者格式化方法格式化字符串。不過也不能一概而論,你需要在+和%之間權衡。正確示范#

更推薦

x

=

f'name:

{name};

score:

{n}'

#

Python3.6+

以上支持

x

=

'name:

{name};

score:

{n}'.format(name=name,

n=n)

x

=

'name:

{name};

score:

{n}'.format(**{"name":

name,

"n":

n})

x

=

'name:

%(name)s;

score:

%(n)d'

%

{"name":

name,

"n":

n}

#

可接受

x

=

'%s,

%s!'

%

(imperative,

expletive)

x

=

'{},

{}!'.format(imperative,

expletive)

x

=

'name:

%s;

score:

%d'

%

(name,

n)

x

=

'name:

{};

score:

{}'.format(name,

n)錯誤示范x

=

'%s%s'

%

(a,

b)

#

use

+

in

this

case

x

=

'{}{}'.format(a,

b)

#

use

+

in

this

case

x

=

imperative

+

',

'

+

expletive

+

'!'

x

=

'name:

'

+

name

+

';

score:

'

+

str(n)1.14.2

【推薦】

避免在循環(huán)中用

+

+=

操作符來累加字符串。由于字符串是不可變的,這樣做會創(chuàng)建不必要的臨時對象,并且導致二次方而不是線性的運行時間。作為替代方案,你可以將每個子串加入列表,然后在循環(huán)結束后用

.join

連接列表。(也可以將每個子串寫入一個io.StringIO緩存中。)pylint:consider-using-join.正確示范items

=

['<table>']

for

last_name,

first_name

in

employee_list:

items.append('<tr><td>%s,

%s</td></tr>'

%

(last_name,

first_name))

items.append('</table>')

employee_table

=

''.join(items)錯誤示范employee_table

=

'<table>'

for

last_name,

first_name

in

employee_list:

employee_table

+=

'<tr><td>%s,

%s</td></tr>'

%

(last_name,

first_name)

employee_table

+=

'</table>'1.14.3

【推薦】

在同一個文件中,保持使用字符串引號的一致性。使用單引號'

或者雙引號

"

引用字符串,并在同一文件中一直沿用這種風格。當字符串中包含單引號或者雙引號時,為提高可讀性,使用另外一種引號,代替轉義字符。正確示范Python('Why

are

you

hiding

your

eyes?')

Gollum("I'm

scared

of

lint

errors.")

Narrator('"Good!"

thought

a

happy

Python

reviewer.')錯誤示范Python("Why

are

you

hiding

your

eyes?")

Gollum('The

lint.

It

burns.

It

burns

us.')

Gollum("Always

the

great

lint.

Watching.

Watching.")1.14.4

【必須】

如果要引用的字符串為多行時,需要使用雙引號引用字符串。1.14.5

【必須】

文檔字符串(docstring)必須使用三重雙引號

"""。1.14.6

【可選】

避免在代碼中使用三重引號

""",因為當使用三重引號時,縮進方式與其他部分不一致,容易引起誤導。正確示范print("This

is

much

nicer.\n"

"Do

it

this

way.\n")錯誤示范print("""This

is

pretty

ugly.

Don't

do

this.

""")1.14.7

【推薦】

檢查前綴和后綴時,使用

.startswith()

.endswith()

代替字符串切片。正確示范if

foo.startswith('bar'):錯誤示范if

foo[:3]

==

'bar':1.15文件和sockets1.15.1

【必須】

在文件和sockets結束時,顯式的關閉它。除文件外,sockets或其他類似文件的對象在沒有必要的情況下打開,會有許多副作用,例如:它們可能會消耗有限的系統(tǒng)資源,如文件描述符。如果這些資源在使用后沒有及時歸還系統(tǒng),那么用于處理這些對象的代碼會將資源消耗殆盡。持有文件將會阻止對于文件的其他諸如移動、刪除之類的操作。僅僅是從邏輯上關閉文件和sockets,那么它們仍然可能會被其共享的程序在無意中進行讀或者寫操作。只有當它們真正被關閉后,對于它們嘗試進行讀或者寫操作將會拋出異常,并使得問題快速顯現(xiàn)出來。而且,幻想當文件對象析構時,文件和sockets會自動關閉,試圖將文件對象的生命周期和文件的狀態(tài)綁定在一起的想法,都是不現(xiàn)實的。因為有如下原因:沒有任何方法可以確保運行環(huán)境會真正的執(zhí)行文件的析構。不同的Python實現(xiàn)采用不同的內存管理技術,比如延時垃圾處理機制。延時垃圾處理機制可能會導致對象生命周期被任意無限制的延長。對于文件意外的引用,會導致對于文件的持有時間超出預期(比如對于異常的跟蹤,包含有全局變量等)。1.15.2

【推薦】

推薦使用

with

語句管理文件。with

open("hello.txt")

as

hello_file:

for

line

in

hello_file:

print(line)對于不支持使用

with

語句的類似文件的對象,使用

contextlib.closing():import

contextlib

with

contextlib.closing(urllib.urlopen("/"))

as

front_page:

for

line

in

front_page:

print(line)LegacyAppEngine中Python2.5的代碼如使用

with

語句,需要添加

from__future__importwith_statement.1.16訪問控制在Python中,對于瑣碎又不太重要的訪問函數(shù),應該直接使用公有變量來取代它們,這樣可以避免額外的函數(shù)調用開銷。當添加更多功能時,也可以用屬性(property)來保持語法的一致性。1.16.1

【推薦】

如果訪問屬性后需要復雜的邏輯處理,或者變量的訪問開銷很顯著,那么應該使用像

get_foo()

set_foo()

這樣的函數(shù)調用。如果之前的代碼行為已經通過屬性(property)訪問,那么就不要將新的訪問函數(shù)與屬性綁定。否則,任何試圖通過老方法訪問變量的代碼就沒法運行,使用者也就會意識到復雜性發(fā)生了變化。(如果可以重構這個代碼是最好的了)1.17Main即使是一個打算被用作腳本的文件,也應該是可導入的。并且簡單的導入不應該導致這個腳本的主功能(mainfunctionality)被執(zhí)行,這是一種副作用。主功能應該放在一個main()函數(shù)中。1.17.1

【必須】

所有的文件都應該可以被導入。對不需要作為程序入口地方添加

if__name__=='__main__'

。在Python中,pydoc以及單元測試要求模塊必須是可導入的。你的代碼應該在執(zhí)行主程序前總是檢查

if__name__=='__main__'

,這樣當模塊被導入時主程序就不會被執(zhí)行。所有的頂級代碼在模塊導入時都會被執(zhí)行。要小心不要去調用函數(shù),創(chuàng)建對象,或者執(zhí)行那些不應該在使用pydoc時執(zhí)行的操作。正確示范def

main():

...

if

__name__

==

'__main__':

main()1.18命名module_name,package_name,ClassName,method_name,ExceptionName,function_name,GLOBAL_VAR_NAME,instance_var_name,function_parameter_name,local_var_name.應該避免的名稱:單字符名稱,除了計數(shù)器和迭代器。包/模塊名中的連字符(-)。雙下劃線開頭并結尾的名稱(Python保留,例如__init__)。1.18.1

【推薦】

命名約定規(guī)則如下:pylint:invalid-name.所謂內部(Internal)

表示僅模塊內可用,或者,在類內是保護或私有的。用單下劃線

(_)

開頭表示模塊變量或函數(shù)是protected的(使用frommoduleimport*時不會包含)。用雙下劃線

(__)

開頭的實例變量或方法表示類內私有。將相關的類和頂級函數(shù)放在同一個模塊里。不像Java,沒必要限制一個類一個模塊。對類名使用大寫字母開頭的單詞(如CapWords,即Pascal風格),但是模塊名應該用小寫加下劃線的方式(如lower_with_under.py)。盡管已經有很多現(xiàn)存的模塊使用類似于CapWords.py這樣的命名,但現(xiàn)在已經不鼓勵這樣做,因為如果模塊名碰巧和類名一致,這會讓人困擾。Python之父Guido推薦的規(guī)范:TypePublicInternalModuleslower_with_under_lower_with_underPackageslower_with_underClassesCapWords_CapWordsExceptionsCapWordsFunctionslower_with_under()_lower_with_under()Global/ClassConstantsCAPS_WITH_UNDER_CAPS_WITH_UNDERGlobal/ClassVariableslower_with_under_lower_with_underInstanceVariableslower_with_under_lower_with_under(protected)or__lower_with_under(private)MethodNameslower_with_under()_lower_with_under()(protected)or__lower_with_under()(private)Function/MethodParameterslower_with_underLocalVariableslower_with_under二、編碼規(guī)范2.1三目運算符2.1.1

【必須】

三目操作符判斷,python不支持三目運算符,但可使用如下方式,禁止使用復雜難懂的邏輯判斷。正確示范x

=

a

if

a

>=

b

else

b錯誤示范x

=

a

>=

b

and

a

or

b2.2None條件的判斷2.2.1

【必須】

為提升可讀性,在判斷條件中應使用

isnot,而不使用

not...is。pycodestyle:E714testforobjectidentityshouldbe'isnot'.正確示范if

foo

is

not

None:錯誤示范if

not

foo

is

None:2.3lambda匿名函數(shù)2.3.1

【必須】

使用def定義簡短函數(shù)而不是使用lambda。pycodestyle:E731donotassignalambdaexpression,useadef.使用def的方式有助于在trackbacks中打印有效的類型信息,明確使用

f

函數(shù)而不是一個lambda的調用。正確示范def

f(x):

return

2

*

x錯誤示范f

=

lambda

x:

2

*

x2.4異常2.4.1

【必須】

異常類繼承自

Exception,而不是

BaseException。2.4.2

【必須】

使用新版本拋出異常的方式,禁止使用廢棄的方式。pycodestyle:W602deprecatedformofraisingexception.正確示范raise

ValueError('message')錯誤示范raise

ValueError,

'message'2.4.3

【必須】

捕獲異常時,需要指明具體異常,而不是捕獲所有異常。除非已經在當前線程的最外層(記得還是要打印一條traceback)。pylint:broad-except,

bare-except.正確示范try:

import

platform_specific_module

except

ImportError:

platform_specific_module

=

None

try:

do_something()

except

Exception

as

ex:

#

pylint:

disable=broad-except

log.exception(ex)

#

應將錯誤堆棧打印到日志文件中,以供后續(xù)排查。

handle_exception_or_not()

#

除打印日志外,還可以進一步處理如清理資源等,可選。錯誤示范try:

import

platform_specific_module

except

Exception:

#

broad-except

platform_specific_module

=

None

try:

do_something()

except

Exception:

#

框架等未明確異常場景,建議增加

traceback

打印

pass2.4.4

【推薦】

建議在代碼中用異常替代函數(shù)的錯誤返回碼。正確示范def

write_data():

if

check_file_exist():

do_something()

else:

raise

FileNotExist()錯誤示范def

write_data():

if

check_file_exist():

do_something()

return

0

else:

return

FILE_NOT_EXIST2.4.5

【推薦】

except

子句中重新拋出原有異常時,不能用

raiseex,而是用

raise。正確示范try:

raise

MyException()

except

MyException

as

ex:

try_handle_exception()

raise

#

可以保留原始的

traceback

try:

raise

MyException()

except

MyException

as

ex:

log.exception(ex)

raise

AnotherException(str(ex))

#

允許的,建議保留好之前的異常棧信息,用于定位問題錯誤示范try:

raise

MyException()

except

MyException

as

ex:

try_handle_exception()

raise

ex

#

異常棧信息從這里開始,原始的raise異常棧信息消息2.4.6

【推薦】

所有

try/except

子句的代碼要盡可的少,以免屏蔽其他的錯誤。正確示范try:

value

=

collection[key]

except

KeyError:

return

key_not_found(key)

else:

return

handle_value(value)錯誤示范try:

#

范圍太廣

return

handle_value(collection[key])

except

KeyError:

#

會捕捉到

handle_value()

中的

KeyError

return

key_not_found(key)2.5條件表達式2.5.1

【推薦】

函數(shù)或者方法在沒有返回時要明確返回

None。pylint:inconsistent-return-statements.正確示范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)錯誤示范def

foo(x):

if

x

>=

0:

return

math.sqrt(x)

def

bar(x):

if

x

<

0:

return

return

math.sqrt(x)2.5.2

【推薦】

對于未知的條件分支或者不應該進入的分支,建議拋出異常,而不是返回一個值(比如說

None

False)。正確示范def

f(x):

if

x

in

('SUCCESS',):

return

True

else:

raise

MyException()

#

如果一定不會走到的條件,可以增加異常,防止將來未知的語句執(zhí)行。錯誤示范def

f(x):

if

x

in

('SUCCESS',):

return

True

return

None2.5.3

【可選】

if

else

盡量一起出現(xiàn),而不是全部都是

if

子句。正確示范if

condition:

do_something()

else:

#

增加說明注釋

pass

if

condition:

do_something()

#

這里增加注釋說明為什么不用寫else子句

#

else:

#

pass錯誤示范if

condition:

do_something()

if

another_condition:

#

不能確定是否筆誤為

elif

,還是開啟全新一個if條件

do_another_something()

else:

do_else_something()2.6True/False布爾運算2.6.1

【必須】

不要用

==

True、

False

進行布爾運算。pylint:singleton-comparison.正確示范if

greeting:

pass錯誤示范if

greeting

==

True:

pass

if

greeting

is

True:

#

Worse

pass2.6.2

【必須】

對序列(字符串、列表、元組),空序列為false的情況。pylint:len-as-condition.正確示范if

not

seq:

pass

if

seq:

pass錯誤示范if

len(seq):

pass

if

not

len(seq):

pass2.7列表推導式2.7.1

【必須】

禁止超過1個for語句或過濾器表達式,否則使用傳統(tǒng)

for

循環(huán)語句替代。正確示范number_list

=

[1,

2,

3,

10,

20,

55]

odd

=

[i

for

i

in

number_list

if

i

%

2

==

1]

result

=

[]

for

x

in

range(10):

for

y

in

range(5):

if

x

*

y

>

10:

result.append((x,

y))錯誤示范result

=

[(x,

y)

for

x

in

range(10)

for

y

in

range(5)

if

x

*

y

>

10]

#

for

語句2.7.2

【推薦】

列表推導式適用于簡單場景。如果語句過長,每個部分應該單獨置于一行:映射表達式,for語句,過濾器表達式。正確示范fizzbuzz

=

[]

for

n

in

range(100):

if

n

%

3

==

0

and

n

%

5

==

0:

fizzbuzz.append(f'fizzbuzz

{n}')

elif

n

%

3

==

0:

fizzbuzz.append(f'fizz

{n}')

elif

n

%

5

==

0:

fizzbuzz.append(f'buzz

{n}')

else:

fizzbuzz.append(n)

for

n

in

range(1,

11):

print(n)錯誤示范#

條件過于復雜,應該采用for語句展開

fizzbuzz

=

[

f'fizzbuzz

{n}'

if

n

%

3

==

0

and

n

%

5

==

0

else

f'fizz

{n}'

if

n

%

3

==

0

else

f'buzz

{n}'

if

n

%

5

==

0

else

n

for

n

in

range(100)

]

[print(n)

for

n

in

range(1,

11)]

#

無返回值2.8函數(shù)2.8.1

【必須】

模塊內部禁止定義重復函數(shù)聲明。pylint:function-redefined.禁止重復

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論