Movatterモバイル変換


[0]ホーム

URL:


styleguide

Google Python Style Guide

Table of Contents

1 Background

Python is the main dynamic language used at Google. This style guide is a listofdos and don’ts for Python programs.

To help you format code correctly, we’ve created asettings file for Vim. For Emacs, the default settings should be fine.

Many teams use theBlack orPyinkauto-formatter to avoid arguing over formatting.

2 Python Language Rules

2.1 Lint

Runpylint over your code using thispylintrc.

2.1.1 Definition

pylintis a tool for finding bugs and style problems in Python source code. It findsproblems that are typically caught by a compiler for less dynamic languages likeC and C++. Because of the dynamic nature of Python, somewarnings may be incorrect; however, spurious warnings should be fairlyinfrequent.

2.1.2 Pros

Catches easy-to-miss errors like typos, using-vars-before-assignment, etc.

2.1.3 Cons

pylintisn’t perfect. To take advantage of it, sometimes we’ll need to write around it,suppress its warnings or fix it.

2.1.4 Decision

Make sure you runpylinton your code.

Suppress warnings if they are inappropriate so that other issues are not hidden.To suppress warnings, you can set a line-level comment:

defdo_PUT(self):# WSGI name, so pylint: disable=invalid-name...

pylintwarnings are each identified by symbolic name (empty-docstring)Google-specific warnings start withg-.

If the reason for the suppression is not clear from the symbolic name, add anexplanation.

Suppressing in this way has the advantage that we can easily search forsuppressions and revisit them.

You can get a list ofpylintwarnings by doing:

pylint--list-msgs

To get more information on a particular message, use:

pylint--help-msg=invalid-name

Preferpylint: disable to the deprecated older formpylint: disable-msg.

Unused argument warnings can be suppressed by deleting the variables at thebeginning of the function. Always include a comment explaining why you aredeleting it. “Unused.” is sufficient. For example:

defviking_cafe_order(spam:str,beans:str,eggs:str|None=None)->str:delbeans,eggs# Unused by vikings.returnspam+spam+spam

Other common forms of suppressing this warning include using ‘_’ as theidentifier for the unused argument or prefixing the argument name with‘unused_’, or assigning them to ‘_’. These forms are allowed but no longerencouraged. These break callers that pass arguments by name and do not enforcethat the arguments are actually unused.

2.2 Imports

Useimport statements for packages and modules only, not for individual types,classes, or functions.

2.2.1 Definition

Reusability mechanism for sharing code from one module to another.

2.2.2 Pros

The namespace management convention is simple. The source of each identifier isindicated in a consistent way;x.Obj says that objectObj is defined inmodulex.

2.2.3 Cons

Module names can still collide. Some module names are inconveniently long.

2.2.4 Decision

For example the modulesound.effects.echo may be imported as follows:

fromsound.effectsimportecho...echo.EchoFilter(input,output,delay=0.7,atten=4)

Do not use relative names in imports. Even if the module is in the same package,use the full package name. This helps prevent unintentionally importing apackage twice.

2.2.4.1 Exemptions

Exemptions from this rule:

2.3 Packages

Import each module using the full pathname location of the module.

2.3.1 Pros

Avoids conflicts in module names or incorrect imports due to the module searchpath not being what the author expected. Makes it easier to find modules.

2.3.2 Cons

Makes it harder to deploy code because you have to replicate the packagehierarchy. Not really a problem with modern deployment mechanisms.

2.3.3 Decision

All new code should import each module by its full package name.

Imports should be as follows:

Yes:# Reference absl.flags in code with the complete name (verbose).importabsl.flagsfromdoctor.whoimportjodie_FOO=absl.flags.DEFINE_string(...)
Yes:# Reference flags in code with just the module name (common).fromabslimportflagsfromdoctor.whoimportjodie_FOO=flags.DEFINE_string(...)

(assume this file lives indoctor/who/ wherejodie.py also exists)

No:# Unclear what module the author wanted and what will be imported.  The actual# import behavior depends on external factors controlling sys.path.# Which possible jodie module did the author intend to import?importjodie

The directory the main binary is located in should not be assumed to be insys.path despite that happening in some environments. This being the case,code should assume thatimport jodie refers to a third-party or top-levelpackage namedjodie, not a localjodie.py.

2.4 Exceptions

Exceptions are allowed but must be used carefully.

2.4.1 Definition

Exceptions are a means of breaking out of normal control flow to handle errorsor other exceptional conditions.

2.4.2 Pros

The control flow of normal operation code is not cluttered by error-handlingcode. It also allows the control flow to skip multiple frames when a certaincondition occurs, e.g., returning from N nested functions in one step instead ofhaving to plumb error codes through.

2.4.3 Cons

May cause the control flow to be confusing. Easy to miss error cases when makinglibrary calls.

2.4.4 Decision

Exceptions must follow certain conditions:

2.5 Mutable Global State

Avoid mutable global state.

2.5.1 Definition

Module-level values or class attributes that can get mutated during programexecution.

2.5.2 Pros

Occasionally useful.

2.5.3 Cons

2.5.4 Decision

Avoid mutable global state.

In those rare cases where using global state is warranted, mutable globalentities should be declared at the module level or as a class attribute and madeinternal by prepending an_ to the name. If necessary, external access tomutable global state must be done through public functions or class methods. SeeNaming below. Please explain the design reasons why mutableglobal state is being used in a comment or a doc linked to from a comment.

Module-level constants are permitted and encouraged. For example:_MAX_HOLY_HANDGRENADE_COUNT = 3 for an internal use constant orSIR_LANCELOTS_FAVORITE_COLOR = "blue" for a public API constant. Constantsmust be named using all caps with underscores. SeeNamingbelow.

2.6 Nested/Local/Inner Classes and Functions

Nested local functions or classes are fine when used to close over a localvariable. Inner classes are fine.

2.6.1 Definition

A class can be defined inside of a method, function, or class. A function can bedefined inside a method or function. Nested functions have read-only access tovariables defined in enclosing scopes.

2.6.2 Pros

Allows definition of utility classes and functions that are only used inside ofa very limited scope. VeryADT-y. Commonly used forimplementing decorators.

2.6.3 Cons

Nested functions and classes cannot be directly tested. Nesting can make theouter function longer and less readable.

2.6.4 Decision

They are fine with some caveats. Avoid nested functions or classes except whenclosing over a local value other thanself orcls. Do not nest a functionjust to hide it from users of a module. Instead, prefix its name with an _ atthe module level so that it can still be accessed by tests.

2.7 Comprehensions & Generator Expressions

Okay to use for simple cases.

2.7.1 Definition

List, Dict, and Set comprehensions as well as generator expressions provide aconcise and efficient way to create container types and iterators withoutresorting to the use of traditional loops,map(),filter(), orlambda.

2.7.2 Pros

Simple comprehensions can be clearer and simpler than other dict, list, or setcreation techniques. Generator expressions can be very efficient, since theyavoid the creation of a list entirely.

2.7.3 Cons

Complicated comprehensions or generator expressions can be hard to read.

2.7.4 Decision

Comprehensions are allowed, however multiplefor clauses or filter expressionsare not permitted. Optimize for readability, not conciseness.

Yes:result=[mapping_exprforvalueiniterableiffilter_expr]result=[is_valid(metric={'key':value})forvalueininteresting_iterableifa_longer_filter_expression(value)]descriptive_name=[transform({'key':key,'value':value},color='black')forkey,valueingenerate_iterable(some_input)ifcomplicated_condition_is_met(key,value)]result=[]forxinrange(10):foryinrange(5):ifx*y>10:result.append((x,y))return{x:complicated_transform(x)forxinlong_generator_function(parameter)ifxisnotNone}return(x**2forxinrange(10))unique_names={user.nameforuserinusersifuserisnotNone}
No:result=[(x,y)forxinrange(10)foryinrange(5)ifx*y>10]return((x,y,z)forxinrange(5)foryinrange(5)ifx!=yforzinrange(5)ify!=z)

2.8 Default Iterators and Operators

Use default iterators and operators for types that support them, like lists,dictionaries, and files.

2.8.1 Definition

Container types, like dictionaries and lists, define default iterators andmembership test operators (“in” and “not in”).

2.8.2 Pros

The default iterators and operators are simple and efficient. They express theoperation directly, without extra method calls. A function that uses defaultoperators is generic. It can be used with any type that supports the operation.

2.8.3 Cons

You can’t tell the type of objects by reading the method names (unless thevariable has type annotations). This is also an advantage.

2.8.4 Decision

Use default iterators and operators for types that support them, like lists,dictionaries, and files. The built-in types define iterator methods, too. Preferthese methods to methods that return lists, except that you should not mutate acontainer while iterating over it.

Yes:forkeyinadict:...ifobjinalist:...forlineinafile:...fork,vinadict.items():...
No:forkeyinadict.keys():...forlineinafile.readlines():...

2.9 Generators

Use generators as needed.

2.9.1 Definition

A generator function returns an iterator that yields a value each time itexecutes a yield statement. After it yields a value, the runtime state of thegenerator function is suspended until the next value is needed.

2.9.2 Pros

Simpler code, because the state of local variables and control flow arepreserved for each call. A generator uses less memory than a function thatcreates an entire list of values at once.

2.9.3 Cons

Local variables in the generator will not be garbage collected until thegenerator is either consumed to exhaustion or itself garbage collected.

2.9.4 Decision

Fine. Use “Yields:” rather than “Returns:” in the docstring for generatorfunctions.

If the generator manages an expensive resource, make sure to force the clean up.

A good way to do the clean up is by wrapping the generator with a contextmanagerPEP-0533.

2.10 Lambda Functions

Okay for one-liners. Prefer generator expressions overmap() orfilter()with alambda.

2.10.1 Definition

Lambdas define anonymous functions in an expression, as opposed to a statement.

2.10.2 Pros

Convenient.

2.10.3 Cons

Harder to read and debug than local functions. The lack of names means stacktraces are more difficult to understand. Expressiveness is limited because thefunction may only contain an expression.

2.10.4 Decision

Lambdas are allowed. If the code inside the lambda function spans multiple linesor is longer than 60-80 chars, it might be better to define it as a regularnested function.

For common operations like multiplication, use the functions from theoperatormodule instead of lambda functions. For example, preferoperator.mul tolambda x, y: x * y.

2.11 Conditional Expressions

Okay for simple cases.

2.11.1 Definition

Conditional expressions (sometimes called a “ternary operator”) are mechanismsthat provide a shorter syntax for if statements. For example:x = 1 if condelse 2.

2.11.2 Pros

Shorter and more convenient than an if statement.

2.11.3 Cons

May be harder to read than an if statement. The condition may be difficult tolocate if the expression is long.

2.11.4 Decision

Okay to use for simple cases. Each portion must fit on one line:true-expression, if-expression, else-expression. Use a complete if statementwhen things get more complicated.

Yes:one_line='yes'ifpredicate(value)else'no'slightly_split=('yes'ifpredicate(value)else'no, nein, nyet')the_longest_ternary_style_that_can_be_done=('yes, true, affirmative, confirmed, correct'ifpredicate(value)else'no, false, negative, nay')
No:bad_line_breaking=('yes'ifpredicate(value)else'no')portion_too_long=('yes'ifsome_long_module.some_long_predicate_function(really_long_variable_name)else'no, false, negative, nay')

2.12 Default Argument Values

Okay in most cases.

2.12.1 Definition

You can specify values for variables at the end of a function’s parameter list,e.g.,def foo(a, b=0):. Iffoo is called with only one argument,b is setto 0. If it is called with two arguments,b has the value of the secondargument.

2.12.2 Pros

Often you have a function that uses lots of default values, but on rareoccasions you want to override the defaults. Default argument values provide aneasy way to do this, without having to define lots of functions for the rareexceptions. As Python does not support overloaded methods/functions, defaultarguments are an easy way of “faking” the overloading behavior.

2.12.3 Cons

Default arguments are evaluated once at module load time. This may causeproblems if the argument is a mutable object such as a list or a dictionary. Ifthe function modifies the object (e.g., by appending an item to a list), thedefault value is modified.

2.12.4 Decision

Okay to use with the following caveat:

Do not use mutable objects as default values in the function or methoddefinition.

Yes:deffoo(a,b=None):ifbisNone:b=[]Yes:deffoo(a,b:Sequence|None=None):ifbisNone:b=[]Yes:deffoo(a,b:Sequence=()):# Empty tuple OK since tuples are immutable....
fromabslimportflags_FOO=flags.DEFINE_string(...)No:deffoo(a,b=[]):...No:deffoo(a,b=time.time()):# Is `b` supposed to represent when this module was loaded?...No:deffoo(a,b=_FOO.value):# sys.argv has not yet been parsed......No:deffoo(a,b:Mapping={}):# Could still get passed to unchecked code....

2.13 Properties

Properties may be used to control getting or setting attributes that requiretrivial computations or logic. Property implementations must match the generalexpectations of regular attribute access: that they are cheap, straightforward,and unsurprising.

2.13.1 Definition

A way to wrap method calls for getting and setting an attribute as a standardattribute access.

2.13.2 Pros

2.13.3 Cons

2.13.4 Decision

Properties are allowed, but, like operator overloading, should only be used whennecessary and match the expectations of typical attribute access; follow thegetters and setters rules otherwise.

For example, using a property to simply both get and set an internal attributeisn’t allowed: there is no computation occurring, so the property is unnecessary(make the attribute public instead). In comparison,using a property to control attribute access or to calculate atriviallyderived value is allowed: the logic is simple and unsurprising.

Properties should be created with the@propertydecorator. Manually implementing aproperty descriptor is considered apower feature.

Inheritance with properties can be non-obvious. Do not use properties toimplement computations a subclass may ever want to override and extend.

2.14 True/False Evaluations

Use the “implicit” false if at all possible (with a few caveats).

2.14.1 Definition

Python evaluates certain values asFalse when in a boolean context. A quick“rule of thumb” is that all “empty” values are considered false, so0, None,[], {}, '' all evaluate as false in a boolean context.

2.14.2 Pros

Conditions using Python booleans are easier to read and less error-prone. Inmost cases, they’re also faster.

2.14.3 Cons

May look strange to C/C++ developers.

2.14.4 Decision

Use the “implicit” false if possible, e.g.,if foo: rather thanif foo !=[]:. There are a few caveats that you should keep in mind though:

2.16 Lexical Scoping

Okay to use.

2.16.1 Definition

A nested Python function can refer to variables defined in enclosing functions,but cannot assign to them. Variable bindings are resolved using lexical scoping,that is, based on the static program text. Any assignment to a name in a blockwill cause Python to treat all references to that name as a local variable, evenif the use precedes the assignment. If a global declaration occurs, the name istreated as a global variable.

An example of the use of this feature is:

defget_adder(summand1:float)->Callable[[float],float]:"""Returns a function that adds numbers to a given number."""defadder(summand2:float)->float:returnsummand1+summand2returnadder

2.16.2 Pros

Often results in clearer, more elegant code. Especially comforting toexperienced Lisp and Scheme (and Haskell and ML and …) programmers.

2.16.3 Cons

Can lead to confusing bugs, such as this example based onPEP-0227:

i=4deffoo(x:Iterable[int]):defbar():print(i,end='')# ...# A bunch of code here# ...foriinx:# Ah, i *is* local to foo, so this is what bar seesprint(i,end='')bar()

Sofoo([1, 2, 3]) will print1 2 3 3,not1 2 3 4.

2.16.4 Decision

Okay to use.

2.17 Function and Method Decorators

Use decorators judiciously when there is a clear advantage. Avoidstaticmethodand limit use ofclassmethod.

2.17.1 Definition

Decorators for Functions and Methods(a.k.a “the@ notation”). One common decorator is@property, used forconverting ordinary methods into dynamically computed attributes. However, thedecorator syntax allows for user-defined decorators as well. Specifically, forsome functionmy_decorator, this:

classC:@my_decoratordefmethod(self):# method body ...

is equivalent to:

classC:defmethod(self):# method body ...method=my_decorator(method)

2.17.2 Pros

Elegantly specifies some transformation on a method; the transformation mighteliminate some repetitive code, enforce invariants, etc.

2.17.3 Cons

Decorators can perform arbitrary operations on a function’s arguments or returnvalues, resulting in surprising implicit behavior. Additionally, decoratorsexecute at object definition time. For module-level objects (classes, modulefunctions, …) this happens at import time. Failures in decorator code arepretty much impossible to recover from.

2.17.4 Decision

Use decorators judiciously when there is a clear advantage. Decorators shouldfollow the same import and naming guidelines as functions. A decorator docstringshould clearly state that the function is a decorator. Write unit tests fordecorators.

Avoid external dependencies in the decorator itself (e.g. don’t rely on files,sockets, database connections, etc.), since they might not be available when thedecorator runs (at import time, perhaps frompydoc or other tools). Adecorator that is called with valid parameters should (as much as possible) beguaranteed to succeed in all cases.

Decorators are a special case of “top-level code” - seemain formore discussion.

Never usestaticmethod unless forced to in order to integrate with an APIdefined in an existing library. Write a module-level function instead.

Useclassmethod only when writing a named constructor, or a class-specificroutine that modifies necessary global state such as a process-wide cache.

2.18 Threading

Do not rely on the atomicity of built-in types.

While Python’s built-in data types such as dictionaries appear to have atomicoperations, there are corner cases where they aren’t atomic (e.g. if__hash__or__eq__ are implemented as Python methods) and their atomicity should not berelied upon. Neither should you rely on atomic variable assignment (since thisin turn depends on dictionaries).

Use thequeue module’sQueue data type as the preferred way to communicatedata between threads. Otherwise, use thethreading module and its lockingprimitives. Prefer condition variables andthreading.Condition instead ofusing lower-level locks.

2.19 Power Features

Avoid these features.

2.19.1 Definition

Python is an extremely flexible language and gives you many fancy features suchas custom metaclasses, access to bytecode, on-the-fly compilation, dynamicinheritance, object reparenting, import hacks, reflection (e.g. some uses ofgetattr()), modification of system internals,__del__ methods implementingcustomized cleanup, etc.

2.19.2 Pros

These are powerful language features. They can make your code more compact.

2.19.3 Cons

It’s very tempting to use these “cool” features when they’re not absolutelynecessary. It’s harder to read, understand, and debug code that’s using unusualfeatures underneath. It doesn’t seem that way at first (to the original author),but when revisiting the code, it tends to be more difficult than code that islonger but is straightforward.

2.19.4 Decision

Avoid these features in your code.

Standard library modules and classes that internally use these features are okayto use (for example,abc.ABCMeta,dataclasses, andenum).

2.20 Modern Python: from __future__ imports

New language version semantic changes may be gated behind a special futureimport to enable them on a per-file basis within earlier runtimes.

2.20.1 Definition

Being able to turn on some of the more modern features viafrom __future__import statements allows early use of features from expected future Pythonversions.

2.20.2 Pros

This has proven to make runtime version upgrades smoother as changes can be madeon a per-file basis while declaring compatibility and preventing regressionswithin those files. Modern code is more maintainable as it is less likely toaccumulate technical debt that will be problematic during future runtimeupgrades.

2.20.3 Cons

Such code may not work on very old interpreter versions prior to theintroduction of the needed future statement. The need for this is more common inprojects supporting an extremely wide variety of environments.

2.20.4 Decision

from __future__ imports

Use offrom __future__ import statements is encouraged. It allows a givensource file to start using more modern Python syntax features today. Once you nolonger need to run on a version where the features are hidden behind a__future__ import, feel free to remove those lines.

In code that may execute on versions as old as 3.5 rather than >= 3.7, import:

from__future__importgenerator_stop

For more information read thePython future statement definitionsdocumentation.

Please don’t remove these imports until you are confident the code is only everused in a sufficiently modern environment. Even if you do not currently use thefeature a specific future import enables in your code today, keeping it in placein the file prevents later modifications of the code from inadvertentlydepending on the older behavior.

Use otherfrom __future__ import statements as you see fit.

2.21 Type Annotated Code

You can annotate Python code withtype hints. Type-check the codeat build time with a type checking tool likepytype.In most cases, when feasible, type annotations are in source files. Forthird-party or extension modules, annotations can be instub.pyi files.

2.21.1 Definition

Type annotations (or “type hints”) are for function or method arguments andreturn values:

deffunc(a:int)->list[int]:

You can also declare the type of a variable using similar syntax:

a:SomeType=some_func()

2.21.2 Pros

Type annotations improve the readability and maintainability of your code. Thetype checker will convert many runtime errors to build-time errors, and reduceyour ability to usePower Features.

2.21.3 Cons

You will have to keep the type declarations up to date.You might see type errors that you think arevalid code. Use of atype checkermay reduce your ability to usePower Features.

2.21.4 Decision

You are strongly encouraged to enable Python type analysis when updating code.When adding or modifying public APIs, include type annotations and enablechecking via pytype in the build system. As static analysis is relatively new toPython, we acknowledge that undesired side-effects (such aswronglyinferred types) may prevent adoption by some projects. In those situations,authors are encouraged to add a comment with a TODO or link to a bug describingthe issue(s) currently preventing type annotation adoption in the BUILD file orin the code itself as appropriate.

3 Python Style Rules

3.1 Semicolons

Do not terminate your lines with semicolons, and do not use semicolons to puttwo statements on the same line.

3.2 Line length

Maximum line length is80 characters.

Explicit exceptions to the 80 character limit:

Do not use a backslash forexplicit line continuation.

Instead, make use of Python’simplicit line joining inside parentheses, brackets and braces.If necessary, you can add an extra pair of parentheses around an expression.

Note that this rule doesn’t prohibit backslash-escaped newlines within strings(seebelow).

Yes:foo_bar(self,width,height,color='black',design=None,x='foo',emphasis=None,highlight=0)
Yes:if(width==0andheight==0andcolor=='red'andemphasis=='strong'):(bridge_questions.clarification_on.average_airspeed_of.unladen_swallow)='African or European?'with(very_long_first_expression_function()asspam,very_long_second_expression_function()asbeans,third_thing()aseggs,):place_order(eggs,beans,spam,beans)
No:ifwidth==0andheight==0and \color=='red'andemphasis=='strong':bridge_questions.clarification_on \.average_airspeed_of.unladen_swallow='African or European?'withvery_long_first_expression_function()asspam, \very_long_second_expression_function()asbeans, \third_thing()aseggs:place_order(eggs,beans,spam,beans)

When a literal string won’t fit on a single line, use parentheses for implicitline joining.

x=('This will build a very long long ''long long long long long long string')

Prefer to break lines at the highest possible syntactic level. If you must breaka line twice, break it at the same syntactic level both times.

Yes:bridgekeeper.answer(name="Arthur",quest=questlib.find(owner="Arthur",perilous=True))answer=(a_long_line().of_chained_methods().that_eventually_provides().an_answer())if(configisNoneor'editor.language'notinconfigorconfig['editor.language'].use_spacesisFalse):use_tabs()
No:bridgekeeper.answer(name="Arthur",quest=questlib.find(owner="Arthur",perilous=True))answer=a_long_line().of_chained_methods().that_eventually_provides().an_answer()if(configisNoneor'editor.language'notinconfigorconfig['editor.language'].use_spacesisFalse):use_tabs()

Within comments, put long URLs on their own line if necessary.

Yes:# See details at# http://www.example.com/us/developer/documentation/api/content/v2.0/csv_file_name_extension_full_specification.html
No:# See details at# http://www.example.com/us/developer/documentation/api/content/\# v2.0/csv_file_name_extension_full_specification.html

Make note of the indentation of the elements in the line continuation examplesabove; see theindentation section for explanation.

Docstring summary lines must remain within the 80 characterlimit.

In all other cases where a line exceeds 80 characters, and theBlack orPyinkauto-formatter does not help bring the line below the limit, the line is allowedto exceed this maximum. Authors are encouraged to manually break the line up perthe notes above when it is sensible.

3.3 Parentheses

Use parentheses sparingly.

It is fine, though not required, to use parentheses around tuples. Do not usethem in return statements or conditional statements unless using parentheses forimplied line continuation or to indicate a tuple.

Yes:iffoo:bar()whilex:x=bar()ifxandy:bar()ifnotx:bar()# For a 1 item tuple the ()s are more visually obvious than the comma.onesie=(foo,)returnfooreturnspam,beansreturn(spam,beans)for(x,y)indict.items():...
No:if(x):bar()ifnot(x):bar()return(foo)

3.4 Indentation

Indent your code blocks with4 spaces.

Never use tabs. Implied line continuation should align wrapped elementsvertically (seeline length examples), or use a hanging4-space indent. Closing (round, square or curly) brackets can be placed at theend of the expression, or on separate lines, but then should be indented thesame as the line with the corresponding opening bracket.

Yes:# Aligned with opening delimiter.foo=long_function_name(var_one,var_two,var_three,var_four)meal=(spam,beans)# Aligned with opening delimiter in a dictionary.foo={'long_dictionary_key':value1+value2,...}# 4-space hanging indent; nothing on first line.foo=long_function_name(var_one,var_two,var_three,var_four)meal=(spam,beans)# 4-space hanging indent; nothing on first line,# closing parenthesis on a new line.foo=long_function_name(var_one,var_two,var_three,var_four)meal=(spam,beans,)# 4-space hanging indent in a dictionary.foo={'long_dictionary_key':long_dictionary_value,...}
No:# Stuff on first line forbidden.foo=long_function_name(var_one,var_two,var_three,var_four)meal=(spam,beans)# 2-space hanging indent forbidden.foo=long_function_name(var_one,var_two,var_three,var_four)# No hanging indent in a dictionary.foo={'long_dictionary_key':long_dictionary_value,...}

3.4.1 Trailing commas in sequences of items?

Trailing commas in sequences of items are recommended only when the closingcontainer token],), or} does not appear on the same line as the finalelement, as well as for tuples with a single element. The presence of a trailingcomma is also used as a hint to our Python code auto-formatterBlack orPyinkto direct it to auto-format the container of items to one item per line when the, after the final element is present.

Yes:golomb3=[0,1,3]golomb4=[0,1,4,6,]
No:golomb4=[0,1,4,6,]

3.5 Blank Lines

Two blank lines between top-level definitions, be they function or classdefinitions. One blank line between method definitions and between the docstringof aclass and the first method. No blank line following adef line. Usesingle blank lines as you judge appropriate within functions or methods.

Blank lines need not be anchored to the definition. For example, relatedcomments immediately preceding function, class, and method definitions can makesense. Consider if your comment might be more useful as part of the docstring.

3.6 Whitespace

Follow standard typographic rules for the use of spaces around punctuation.

No whitespace inside parentheses, brackets or braces.

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

No whitespace before a comma, semicolon, or colon. Do use whitespace after acomma, semicolon, or colon, except at the end of the line.

Yes:ifx==4:print(x,y)x,y=y,x
No:ifx==4:print(x,y)x,y=y,x

No whitespace before the open paren/bracket that starts an argument list,indexing or slicing.

Yes:spam(1)
No:spam(1)
Yes:dict['key']=list[index]
No:dict['key']=list[index]

No trailing whitespace.

Surround binary operators with a single space on either side for assignment(=), comparisons (==, <, >, !=, <>, <=, >=, in, not in, is, is not), andBooleans (and, or, not). Use your better judgment for the insertion of spacesaround arithmetic operators (+,-,*,/,//,%,**,@).

Yes:x==1
No:x<1

Never use spaces around= when passing keyword arguments or defining a defaultparameter value, with one exception:when a type annotation is present,do use spacesaround the= for the default parameter value.

Yes:defcomplex(real,imag=0.0):returnMagic(r=real,i=imag)Yes:defcomplex(real,imag:float=0.0):returnMagic(r=real,i=imag)
No:defcomplex(real,imag=0.0):returnMagic(r=real,i=imag)No:defcomplex(real,imag:float=0.0):returnMagic(r=real,i=imag)

Don’t use spaces to vertically align tokens on consecutive lines, since itbecomes a maintenance burden (applies to:,#,=, etc.):

Yes:foo=1000# commentlong_name=2# comment that should not be aligneddictionary={'foo':1,'long_name':2,}
No:foo=1000# commentlong_name=2# comment that should not be aligneddictionary={'foo':1,'long_name':2,}

3.7 Shebang Line

Most.py files do not need to start with a#! line. Start the main file of aprogram with#!/usr/bin/env python3 (to support virtualenvs) or#!/usr/bin/python3 perPEP-394.

This line is used by the kernel to find the Python interpreter, but is ignored by Python when importing modules. It is only necessary on a file intended to be executed directly.

3.8 Comments and Docstrings

Be sure to use the right style for module, function, method docstrings andinline comments.

3.8.1 Docstrings

Python usesdocstrings to document code. A docstring is a string that is thefirst statement in a package, module, class or function. These strings can beextracted automatically through the__doc__ member of the object and are usedbypydoc.(Try runningpydoc on your module to see how it looks.) Always use thethree-double-quote""" format for docstrings (perPEP 257). A docstring should be organizedas a summary line (one physical line not exceeding 80 characters) terminated bya period, question mark, or exclamation point. When writing more (encouraged),this must be followed by a blank line, followed by the rest of the docstringstarting at the same cursor position as the first quote of the first line. Thereare more formatting guidelines for docstrings below.

3.8.2 Modules

Every file should contain license boilerplate. Choose the appropriate boilerplate for the license used by the project (for example, Apache 2.0, BSD, LGPL, GPL).

Files should start with a docstring describing the contents and usage of themodule.

"""A one-line summary of the module or program, terminated by a period.Leave one blank line.  The rest of this docstring should contain anoverall description of the module or program.  Optionally, it may alsocontain a brief description of exported classes and functions and/or usageexamples.Typical usage example:  foo = ClassFoo()  bar = foo.function_bar()"""

3.8.2.1 Test modules

Module-level docstrings for test files are not required. They should be includedonly when there is additional information that can be provided.

Examples include some specifics on how the test should be run, an explanation ofan unusual setup pattern, dependency on the external environment, and so on.

"""This blaze test uses golden files.You can update those files by running`blaze run //foo/bar:foo_test -- --update_golden_files` from the `google3`directory."""

Docstrings that do not provide any new information should not be used.

"""Tests for foo.bar."""

3.8.3 Functions and Methods

In this section, “function” means a method, function, generator, or property.

A docstring is mandatory for every function that has one or more of thefollowing properties:

A docstring should give enough information to write a call to the functionwithout reading the function’s code. The docstring should describe thefunction’s calling syntax and its semantics, but generally not itsimplementation details, unless those details are relevant to how the function isto be used. For example, a function that mutates one of its arguments as a sideeffect should note that in its docstring. Otherwise, subtle but importantdetails of a function’s implementation that are not relevant to the caller arebetter expressed as comments alongside the code than within the function’sdocstring.

The docstring may be descriptive-style ("""Fetches rows from a Bigtable.""")or imperative-style ("""Fetch rows from a Bigtable."""), but the style shouldbe consistent within a file. The docstring for a@property data descriptorshould use the same style as the docstring for an attribute or afunction argument ("""The Bigtable path.""",rather than"""Returns the Bigtable path.""").

Certain aspects of a function should be documented in special sections, listedbelow. Each section begins with a heading line, which ends with a colon. Allsections other than the heading should maintain a hanging indent of two or fourspaces (be consistent within a file). These sections can be omitted in caseswhere the function’s name and signature are informative enough that it can beaptly described using a one-line docstring.

Args:
List each parameter by name. A description should follow the name, and beseparated by a colon followed by either a space or newline. If thedescription is too long to fit on a single 80-character line, use a hangingindent of 2 or 4 spaces more than the parameter name (be consistent with therest of the docstrings in the file). The description should include requiredtype(s) if the code does not contain a corresponding type annotation. If afunction accepts*foo (variable length argument lists) and/or**bar(arbitrary keyword arguments), they should be listed as*foo and**bar.
Returns: (orYields: for generators)
Describe the semantics of the return value, including any type informationthat the type annotation does not provide. If the function only returnsNone, this section is not required. It may also be omitted if the docstringstarts with “Return”, “Returns”, “Yield”, or “Yields” (e.g."""Returns rowfrom Bigtable as a tuple of strings.""")and the opening sentence issufficient to describe the return value. Do not imitate older ‘NumPy style’(example),which frequently documented a tuple return value as if it were multiplereturn values with individual names (never mentioning the tuple). Instead,describe such a return value as: “Returns: A tuple (mat_a, mat_b), wheremat_a is …, and …”. The auxiliary names in the docstring need notnecessarily correspond to any internal names used in the function body (asthose are not part of the API). If the function usesyield (is agenerator), theYields: section should document the object returned bynext(), instead of the generator object itself that the call evaluates to.
Raises:
List all exceptions that are relevant to the interface followed by adescription. Use a similar exception name + colon + space or newline andhanging indent style as described inArgs:. You should not documentexceptions that get raised if the API specified in the docstring is violated(because this would paradoxically make behavior under violation of the APIpart of the API).
deffetch_smalltable_rows(table_handle:smalltable.Table,keys:Sequence[bytes|str],require_all_keys:bool=False,)->Mapping[bytes,tuple[str,...]]:"""Fetches rows from a Smalltable.    Retrieves rows pertaining to the given keys from the Table instance    represented by table_handle.  String keys will be UTF-8 encoded.    Args:        table_handle: An open smalltable.Table instance.        keys: A sequence of strings representing the key of each table          row to fetch.  String keys will be UTF-8 encoded.        require_all_keys: If True only rows with values set for all keys will be          returned.    Returns:        A dict mapping keys to the corresponding table row data        fetched. Each row is represented as a tuple of strings. For        example:        {b'Serak': ('Rigel VII', 'Preparer'),         b'Zim': ('Irk', 'Invader'),         b'Lrrr': ('Omicron Persei 8', 'Emperor')}        Returned keys are always bytes.  If a key from the keys argument is        missing from the dictionary, then that row was not found in the        table (and require_all_keys must have been False).    Raises:        IOError: An error occurred accessing the smalltable.    """

Similarly, this variation onArgs: with a line break is also allowed:

deffetch_smalltable_rows(table_handle:smalltable.Table,keys:Sequence[bytes|str],require_all_keys:bool=False,)->Mapping[bytes,tuple[str,...]]:"""Fetches rows from a Smalltable.    Retrieves rows pertaining to the given keys from the Table instance    represented by table_handle.  String keys will be UTF-8 encoded.    Args:      table_handle:        An open smalltable.Table instance.      keys:        A sequence of strings representing the key of each table row to        fetch.  String keys will be UTF-8 encoded.      require_all_keys:        If True only rows with values set for all keys will be returned.    Returns:      A dict mapping keys to the corresponding table row data      fetched. Each row is represented as a tuple of strings. For      example:      {b'Serak': ('Rigel VII', 'Preparer'),       b'Zim': ('Irk', 'Invader'),       b'Lrrr': ('Omicron Persei 8', 'Emperor')}      Returned keys are always bytes.  If a key from the keys argument is      missing from the dictionary, then that row was not found in the      table (and require_all_keys must have been False).    Raises:      IOError: An error occurred accessing the smalltable.    """

3.8.3.1 Overridden Methods

A method that overrides a method from a base class does not need a docstring ifit is explicitly decorated with@override(fromtyping_extensions ortyping modules), unless the overriding method’sbehavior materially refines the base method’s contract, or details need to beprovided (e.g., documenting additional side effects), in which case a docstringwith at least those differences is required on the overriding method.

fromtyping_extensionsimportoverrideclassParent:defdo_something(self):"""Parent method, includes docstring."""# Child class, method annotated with override.classChild(Parent):@overridedefdo_something(self):pass
# Child class, but without @override decorator, a docstring is required.classChild(Parent):defdo_something(self):pass# Docstring is trivial, @override is sufficient to indicate that docs can be# found in the base class.classChild(Parent):@overridedefdo_something(self):"""See base class."""

3.8.4 Classes

Classes should have a docstring below the class definition describing the class.Public attributes, excludingproperties, should be documentedhere in anAttributes section and follow the same formatting as afunction’sArgs section.

classSampleClass:"""Summary of class here.    Longer class information...    Longer class information...    Attributes:        likes_spam: A boolean indicating if we like SPAM or not.        eggs: An integer count of the eggs we have laid.    """def__init__(self,likes_spam:bool=False):"""Initializes the instance based on spam preference.        Args:          likes_spam: Defines if instance exhibits this preference.        """self.likes_spam=likes_spamself.eggs=0@propertydefbutter_sticks(self)->int:"""The number of butter sticks we have."""

All class docstrings should start with a one-line summary that describes whatthe class instance represents. This implies that subclasses ofExceptionshould also describe what the exception represents, and not the context in whichit might occur. The class docstring should not repeat unnecessary information,such as that the class is a class.

# Yes:classCheeseShopAddress:"""The address of a cheese shop.  ...  """classOutOfCheeseError(Exception):"""No more cheese is available."""
# No:classCheeseShopAddress:"""Class that describes the address of a cheese shop.  ...  """classOutOfCheeseError(Exception):"""Raised when no more cheese is available."""

3.8.5 Block and Inline Comments

The final place to have comments is in tricky parts of the code. If you’re goingto have to explain it at the nextcode review,you should comment it now. Complicated operations get a few lines of commentsbefore the operations commence. Non-obvious ones get comments at the end of theline.

# We use a weighted dictionary search to find out where i is in# the array.  We extrapolate position based on the largest num# in the array and the array size and then do binary search to# get the exact number.ifi&(i-1)==0:# True if i is 0 or a power of 2.

To improve legibility, these comments should start at least 2 spaces away fromthe code with the comment character#, followed by at least one space beforethe text of the comment itself.

On the other hand, never describe the code. Assume the person reading the codeknows Python (though not what you’re trying to do) better than you do.

# BAD COMMENT: Now go through the b array and make sure whenever i occurs# the next element is i+1

3.8.6 Punctuation, Spelling, and Grammar

Pay attention to punctuation, spelling, and grammar; it is easier to readwell-written comments than badly written ones.

Comments should be as readable as narrative text, with proper capitalization andpunctuation. In many cases, complete sentences are more readable than sentencefragments. Shorter comments, such as comments at the end of a line of code, cansometimes be less formal, but you should be consistent with your style.

Although it can be frustrating to have a code reviewer point out that you areusing a comma when you should be using a semicolon, it is very important thatsource code maintain a high level of clarity and readability. Properpunctuation, spelling, and grammar help with that goal.

3.10 Strings

Use anf-string,the% operator, or theformat method for formatting strings, even when theparameters are all strings. Use your best judgment to decide between stringformatting options. A single join with+ is okay but do not format with+.

Yes:x=f'name:{name}; score:{n}'x='%s, %s!'%(imperative,expletive)x='{}, {}'.format(first,second)x='name: %s; score: %d'%(name,n)x='name: %(name)s; score: %(score)d'%{'name':name,'score':n}x='name: {}; score: {}'.format(name,n)x=a+b
No:x=first+', '+secondx='name: '+name+'; score: '+str(n)

Avoid using the+ and+= operators to accumulate a string within a loop. Insome conditions, accumulating a string with addition can lead to quadraticrather than linear running time. Although common accumulations of this sort maybe optimized on CPython, that is an implementation detail. The conditions underwhich an optimization applies are not easy to predict and may change. Instead,add each substring to a list and''.join the list after the loop terminates,or write each substring to anio.StringIO buffer. These techniquesconsistently have amortized-linear run-time complexity.

Yes:items=['<table>']forlast_name,first_nameinemployee_list:items.append('<tr><td>%s, %s</td></tr>'%(last_name,first_name))items.append('</table>')employee_table=''.join(items)
No:employee_table='<table>'forlast_name,first_nameinemployee_list:employee_table+='<tr><td>%s, %s</td></tr>'%(last_name,first_name)employee_table+='</table>'

Be consistent with your choice of string quote character within a file. Pick'or" and stick with it. It is okay to use the other quote character on astring to avoid the need to backslash-escape quote characters within the string.

Yes:Python('Why are you hiding your eyes?')Gollum("I'm scared of lint errors.")Narrator('"Good!" thought a happy Python reviewer.')
No:Python("Why are you hiding your eyes?")Gollum('The lint. It burns. It burns us.')Gollum("Always the great lint. Watching. Watching.")

Prefer""" for multi-line strings rather than'''. Projects may choose touse''' for all non-docstring multi-line strings if and only if they also use' for regular strings. Docstrings must use""" regardless.

Multi-line strings do not flow with the indentation of the rest of the program.If you need to avoid embedding extra space in the string, use eitherconcatenated single-line strings or a multi-line string withtextwrap.dedent()to remove the initial space on each line:

No:long_string="""This is pretty ugly.Don't do this."""
Yes:long_string="""This is fine if your use case can accept      extraneous leading spaces."""
Yes:long_string=("And this is fine if you cannot accept\n"+"extraneous leading spaces.")
Yes:long_string=("And this too is fine if you cannot accept\n""extraneous leading spaces.")
Yes:importtextwraplong_string=textwrap.dedent("""\      This is also fine, because textwrap.dedent()      will collapse common leading spaces in each line.""")

Note that using a backslash here does not violate the prohibition againstexplicit line continuation; in this case, the backslash isescaping a newlinein a string literal.

3.10.1 Logging

For logging functions that expect a pattern-string (with %-placeholders) astheir first argument: Always call them with a string literal (not an f-string!)as their first argument with pattern-parameters as subsequent arguments. Somelogging implementations collect the unexpanded pattern-string as a queryablefield. It also prevents spending time rendering a message that no logger isconfigured to output.

Yes:importtensorflowastflogger=tf.get_logger()logger.info('TensorFlow Version is: %s',tf.__version__)
Yes:importosfromabslimportlogginglogging.info('Current $PAGER is: %s',os.getenv('PAGER',default=''))homedir=os.getenv('HOME')ifhomedirisNoneornotos.access(homedir,os.W_OK):logging.error('Cannot write to home directory, $HOME=%r',homedir)
No:importosfromabslimportlogginglogging.info('Current $PAGER is:')logging.info(os.getenv('PAGER',default=''))homedir=os.getenv('HOME')ifhomedirisNoneornotos.access(homedir,os.W_OK):logging.error(f'Cannot write to home directory, $HOME={homedir!r}')

3.10.2 Error Messages

Error messages (such as: message strings on exceptions likeValueError, ormessages shown to the user) should follow three guidelines:

  1. The message needs to precisely match the actual error condition.

  2. Interpolated pieces need to always be clearly identifiable as such.

  3. They should allow simple automated processing (e.g. grepping).

Yes:ifnot0<=p<=1:raiseValueError(f'Not a probability:{p=}')try:os.rmdir(workdir)exceptOSErroraserror:logging.warning('Could not remove directory (reason: %r): %r',error,workdir)
No:ifp<0orp>1:# PROBLEM: also false for float('nan')!raiseValueError(f'Not a probability:{p=}')try:os.rmdir(workdir)exceptOSError:# PROBLEM: Message makes an assumption that might not be true:# Deletion might have failed for some other reason, misleading# whoever has to debug this.logging.warning('Directory already was deleted: %s',workdir)try:os.rmdir(workdir)exceptOSError:# PROBLEM: The message is harder to grep for than necessary, and# not universally non-confusing for all possible values of `workdir`.# Imagine someone calling a library function with such code# using a name such as workdir = 'deleted'. The warning would read:# "The deleted directory could not be deleted."logging.warning('The %s directory could not be deleted.',workdir)

3.11 Files, Sockets, and similar Stateful Resources

Explicitly close files and sockets when done with them. This rule naturallyextends to closeable resources that internally use sockets, such as databaseconnections, and also other resources that need to be closed down in a similarfashion. To name only a few examples, this also includesmmap mappings,h5py File objects, andmatplotlib.pyplot figure windows.

Leaving files, sockets or other such stateful objects open unnecessarily hasmany downsides:

Furthermore, while files and sockets (and some similarly behaving resources) areautomatically closed when the object is destructed, coupling the lifetime of theobject to the state of the resource is poor practice:

Relying on finalizers to do automatic cleanup that has observable side effectshas been rediscovered over and over again to lead to major problems, across manydecades and multiple languages (see e.g.this articlefor Java).

The preferred way to manage files and similar resources is using thewith statement:

withopen("hello.txt")ashello_file:forlineinhello_file:print(line)

For file-like objects that do not support thewith statement, usecontextlib.closing():

importcontextlibwithcontextlib.closing(urllib.urlopen("http://www.python.org/"))asfront_page:forlineinfront_page:print(line)

In rare cases where context-based resource management is infeasible, codedocumentation must explain clearly how resource lifetime is managed.

3.12 TODO Comments

UseTODO comments for code that is temporary, a short-term solution, orgood-enough but not perfect.

ATODO comment begins with the wordTODO in all caps, a following colon, anda link to a resource that contains the context, ideally a bug reference. A bugreference is preferable because bugs are tracked and have follow-up comments.Follow this piece of context with an explanatory string introduced with a hyphen-. The purpose is to have a consistentTODO format that can be searched to findout how to get more details.

# TODO: crbug.com/192795 - Investigate cpufreq optimizations.

Old style, formerly recommended, but discouraged for use in new code:

# TODO(crbug.com/192795): Investigate cpufreq optimizations.# TODO(yourusername): Use a "\*" here for concatenation operator.

Avoid adding TODOs that refer to an individual or team as the context:

# TODO: @yourusername - File an issue and use a '*' for repetition.

If yourTODO is of the form “At a future date do something” make sure that youeither include a very specific date (“Fix by November 2009”) or a very specificevent (“Remove this code when all clients can handle XML responses.”) thatfuture code maintainers will comprehend. Issues are ideal for tracking this.

3.13 Imports formatting

Imports should be on separate lines; there areexceptions fortyping andcollections.abc imports.

E.g.:

Yes:fromcollections.abcimportMapping,SequenceimportosimportsysfromtypingimportAny,NewType
No:importos,sys

Imports are always put at the top of the file, just after any module commentsand docstrings and before module globals and constants. Imports should begrouped from most generic to least generic:

  1. Python future import statements. For example:

    from__future__importannotations

    Seeabove for more information about those.

  2. Python standard library imports. For example:

    importsys
  3. third-party moduleor package imports. For example:

    importtensorflowastf
  4. Code repositorysub-package imports. For example:

    fromotherproject.aiimportmind
  5. Deprecated: application-specific imports that are part of the sametop-levelsub-package as this file. For example:

    frommyproject.backend.hgwellsimporttime_machine

    You may find older Google Python Style code doing this, but it is no longerrequired.New code is encouraged not to bother with this. Simply treatapplication-specific sub-package imports the same as other sub-packageimports.

Within each grouping, imports should be sorted lexicographically, ignoring case,according to each module’s full package path (thepath infrom path import...). Code may optionally place a blank line between import sections.

importcollectionsimportqueueimportsysfromabslimportappfromabslimportflagsimportbs4importcryptographyimporttensorflowastffrombook.genresimportscififrommyproject.backendimporthuxleyfrommyproject.backend.hgwellsimporttime_machinefrommyproject.backend.state_machineimportmain_loopfromotherproject.aiimportbodyfromotherproject.aiimportmindfromotherproject.aiimportsoul# Older style code may have these imports down here instead:#from myproject.backend.hgwells import time_machine#from myproject.backend.state_machine import main_loop

3.14 Statements

Generally only one statement per line.

However, you may put the result of a test on the same line as the test only ifthe entire statement fits on one line. In particular, you can never do so withtry/except since thetry andexcept can’t both fit on the same line, andyou can only do so with anif if there is noelse.

Yes:iffoo:bar(foo)
No:iffoo:bar(foo)else:baz(foo)try:bar(foo)exceptValueError:baz(foo)try:bar(foo)exceptValueError:baz(foo)

3.15 Getters and Setters

Getter and setter functions (also called accessors and mutators) should be usedwhen they provide a meaningful role or behavior for getting or setting avariable’s value.

In particular, they should be used when getting or setting the variable iscomplex or the cost is significant, either currently or in a reasonable future.

If, for example, a pair of getters/setters simply read and write an internalattribute, the internal attribute should be made public instead. By comparison,if setting a variable means some state is invalidated or rebuilt, it should be asetter function. The function invocation hints that a potentially non-trivialoperation is occurring. Alternatively,properties may be anoption when simple logic is needed, or refactoring to no longer need getters andsetters.

Getters and setters should follow theNaming guidelines, suchasget_foo() andset_foo().

If the past behavior allowed access through a property, do not bind the newgetter/setter functions to the property. Any code still attempting to access thevariable by the old method should break visibly so they are made aware of thechange in complexity.

3.16 Naming

module_name,package_name,ClassName,method_name,ExceptionName,function_name,GLOBAL_CONSTANT_NAME,global_var_name,instance_var_name,function_parameter_name,local_var_name,query_proper_noun_for_thing,send_acronym_via_https.

Names should be descriptive. This includes functions, classes, variables,attributes, files and any other type of named entities.

Avoid abbreviation. In particular, do not use abbreviations that are ambiguousor unfamiliar to readers outside your project, and do not abbreviate by deletingletters within a word.

Always use a.py filename extension. Never use dashes.

3.16.1 Names to Avoid

3.16.2 Naming Conventions

3.16.3 File Naming

Python filenames must have a.py extension and must not contain dashes (-).This allows them to be imported and unittested. If you want an executable to beaccessible without the extension, use a symbolic link or a simple bash wrappercontainingexec "$0.py" "$@".

3.16.4 Guidelines derived fromGuido’s Recommendations

TypePublicInternal
Packageslower_with_under
Moduleslower_with_under_lower_with_under
ClassesCapWords_CapWords
ExceptionsCapWords
Functionslower_with_under()_lower_with_under()
Global/Class ConstantsCAPS_WITH_UNDER_CAPS_WITH_UNDER
Global/Class Variableslower_with_under_lower_with_under
Instance Variableslower_with_under_lower_with_under (protected)
Method Nameslower_with_under()_lower_with_under() (protected)
Function/Method Parameterslower_with_under
Local Variableslower_with_under

3.16.5 Mathematical Notation

For mathematically-heavy code, short variable names that would otherwise violatethe style guide are preferred when they match established notation in areference paper or algorithm.

When using names based on established notation:

  1. Cite the source of all naming conventions, preferably with a hyperlink toacademic resource itself, in a comment or docstring. If the source is notaccessible, clearly document the naming conventions.
  2. Prefer PEP8-compliantdescriptive_names for public APIs, which are muchmore likely to be encountered out of context.
  3. Use a narrowly-scopedpylint: disable=invalid-name directive to silencewarnings. For just a few variables, use the directive as an endline commentfor each one; for more, apply the directive at the beginning of a block.

3.17 Main

In Python,pydoc as well as unit tests require modules to be importable. If afile is meant to be used as an executable, its main functionality should be in amain() function, and your code should always checkif __name__ == '__main__'before executing your main program, so that it is not executed when the moduleis imported.

When usingabsl, useapp.run:

fromabslimportapp...defmain(argv:Sequence[str]):# process non-flag arguments...if__name__=='__main__':app.run(main)

Otherwise, use:

defmain():...if__name__=='__main__':main()

All code at the top level will be executed when the module is imported. Becareful not to call functions, create objects, or perform other operations thatshould not be executed when the file is beingpydoced.

3.18 Function length

Prefer small and focused functions.

We recognize that long functions are sometimes appropriate, so no hard limit isplaced on function length. If a function exceeds about 40 lines, think aboutwhether it can be broken up without harming the structure of the program.

Even if your long function works perfectly now, someone modifying it in a fewmonths may add new behavior. This could result in bugs that are hard to find.Keeping your functions short and simple makes it easier for other people to readand modify your code.

You could find long and complicated functions when working withsomecode. Do not be intimidated by modifying existing code: if working with such afunction proves to be difficult, you find that errors are hard to debug, or youwant to use a piece of it in several different contexts, consider breaking upthe function into smaller and more manageable pieces.

3.19 Type Annotations

3.19.1 General Rules

3.19.2 Line Breaking

Try to follow the existingindentation rules.

After annotating, many function signatures will become “one parameter per line”.To ensure the return type is also given its own line, a comma can be placedafter the last parameter.

defmy_method(self,first_var:int,second_var:Foo,third_var:Bar|None,)->int:...

Always prefer breaking between variables, and not, for example, between variablenames and type annotations. However, if everything fits on the same line, go forit.

defmy_method(self,first_var:int)->int:...

If the combination of the function name, the last parameter, and the return typeis too long, indent by 4 in a new line. When using line breaks, prefer puttingeach parameter and the return type on their own lines and aligning the closingparenthesis with thedef:

Yes:defmy_method(self,other_arg:MyLongType|None,)->tuple[MyLongType1,MyLongType1]:...

Optionally, the return type may be put on the same line as the last parameter:

Okay:defmy_method(self,first_var:int,second_var:int)->dict[OtherLongType,MyLongType]:...

pylintallows you to move the closing parenthesis to a new line and align with theopening one, but this is less readable.

No:defmy_method(self,other_arg:MyLongType|None,)->dict[OtherLongType,MyLongType]:...

As in the examples above, prefer not to break types. However, sometimes they aretoo long to be on a single line (try to keep sub-types unbroken).

defmy_method(self,first_var:tuple[list[MyLongType1],list[MyLongType2]],second_var:list[dict[MyLongType3,MyLongType4]],)->None:...

If a single name and type is too long, consider using analias for the type. The last resort is to break after thecolon and indent by 4.

Yes:defmy_function(long_variable_name:long_module_name.LongTypeName,)->None:...
No:defmy_function(long_variable_name:long_module_name.LongTypeName,)->None:...

3.19.3 Forward Declarations

If you need to use a class name (from the same module) that is not yetdefined – for example, if you need the class name inside the declaration ofthat class, or if you use a class that is defined later in the code – eitherusefrom __future__ import annotations or use a string for the class name.

Yes:from__future__importannotationsclassMyClass:def__init__(self,stack:Sequence[MyClass],item:OtherClass)->None:classOtherClass:...
Yes:classMyClass:def__init__(self,stack:Sequence['MyClass'],item:'OtherClass')->None:classOtherClass:...

3.19.4 Default Values

As perPEP-008, usespaces around the=only for arguments that have both a type annotation anda default value.

Yes:deffunc(a:int=0)->int:...
No:deffunc(a:int=0)->int:...

3.19.5 NoneType

In the Python type system,NoneType is a “first class” type, and for typingpurposes,None is an alias forNoneType. If an argument can beNone, ithas to be declared! You can use| union type expressions (recommended in newPython 3.10+ code), or the olderOptional andUnion syntaxes.

Use explicitX | None instead of implicit. Earlier versions of type checkersalloweda: str = None to be interpreted asa: str | None = None, but that isno longer the preferred behavior.

Yes:defmodern_or_union(a:str|int|None,b:str|None=None)->str:...defunion_optional(a:Union[str,int,None],b:Optional[str]=None)->str:...
No:defnullable_union(a:Union[None,str])->str:...defimplicit_optional(a:str=None)->str:...

3.19.6 Type Aliases

You can declare aliases of complex types. The name of an alias should beCapWorded. If the alias is used only in this module, it should be _Private.

Note that the: TypeAlias annotation is only supported in versions 3.10+.

fromtypingimportTypeAlias_LossAndGradient:TypeAlias=tuple[tf.Tensor,tf.Tensor]ComplexTFMap:TypeAlias=Mapping[str,_LossAndGradient]

3.19.7 Ignoring Types

You can disable type checking on a line with the special comment# type:ignore.

pytype has a disable option for specific errors (similar to lint):

# pytype: disable=attribute-error

3.19.8 Typing Variables

Annotated Assignments
If an internal variable has a type that is hard or impossible to infer,specify its type with an annotated assignment - use a colon and type betweenthe variable name and value (the same as is done with function argumentsthat have a default value):
a:Foo=SomeUndecoratedFunction()
Type Comments
Though you may see them remaining in the codebase (they were necessarybefore Python 3.6), do not add any more uses of a# type: <type name>comment on the end of the line:
a=SomeUndecoratedFunction()# type: Foo

3.19.9 Tuples vs Lists

Typed lists can only contain objects of a single type. Typed tuples can eitherhave a single repeated type or a set number of elements with different types.The latter is commonly used as the return type from a function.

a:list[int]=[1,2,3]b:tuple[int,...]=(1,2,3)c:tuple[int,str,float]=(1,"2",3.5)

3.19.10 Type variables

The Python type system hasgenerics. A typevariable, such asTypeVar andParamSpec, is a common way to use them.

Example:

fromcollections.abcimportCallablefromtypingimportParamSpec,TypeVar_P=ParamSpec("_P")_T=TypeVar("_T")...defnext(l:list[_T])->_T:returnl.pop()defprint_when_called(f:Callable[_P,_T])->Callable[_P,_T]:definner(*args:_P.args,**kwargs:_P.kwargs)->_T:print("Function was called")returnf(*args,**kwargs)returninner

ATypeVar can be constrained:

AddableType=TypeVar("AddableType",int,float,str)defadd(a:AddableType,b:AddableType)->AddableType:returna+b

A common predefined type variable in thetyping module isAnyStr. Use it formultiple annotations that can bebytes orstr and must all be the same type.

fromtypingimportAnyStrdefcheck_length(x:AnyStr)->AnyStr:iflen(x)<=42:returnxraiseValueError()

A type variable must have a descriptive name, unless it meets all of thefollowing criteria:

Yes:_T=TypeVar("_T")_P=ParamSpec("_P")AddableType=TypeVar("AddableType",int,float,str)AnyFunction=TypeVar("AnyFunction",bound=Callable)
No:T=TypeVar("T")P=ParamSpec("P")_T=TypeVar("_T",int,float,str)_F=TypeVar("_F",bound=Callable)

3.19.11 String types

Do not usetyping.Text in new code. It’s only for Python 2/3 compatibility.

Usestr for string/text data. For code that deals with binary data, usebytes.

defdeals_with_text_data(x:str)->str:...defdeals_with_binary_data(x:bytes)->bytes:...

If all the string types of a function are always the same, for example if thereturn type is the same as the argument type in the code above, useAnyStr.

3.19.12 Imports For Typing

For symbols (including types, functions, and constants) from thetyping orcollections.abc modules used to support static analysis and type checking,always import the symbol itself. This keeps common annotations more concise andmatches typing practices used around the world. You are explicitly allowed toimport multiple specific symbols on one line from thetyping andcollections.abc modules. For example:

fromcollections.abcimportMapping,SequencefromtypingimportAny,Generic,cast,TYPE_CHECKING

Given that this way of importing adds items to the local namespace, names intyping orcollections.abc should be treated similarly to keywords, and notbe defined in your Python code, typed or not. If there is a collision between atype and an existing name in a module, import it usingimport x as y.

fromtypingimportAnyasAnyType

When annotating function signatures, prefer abstract container types likecollections.abc.Sequence over concrete types likelist. If you need to use aconcrete type (for example, atuple of typed elements), prefer built-in typesliketuple over the parametric type aliases from thetyping module (e.g.,typing.Tuple).

fromtypingimportList,Tupledeftransform_coordinates(original:List[Tuple[float,float]])->List[Tuple[float,float]]:...
fromcollections.abcimportSequencedeftransform_coordinates(original:Sequence[tuple[float,float]])->Sequence[tuple[float,float]]:...

3.19.13 Conditional Imports

Use conditional imports only in exceptional cases where the additional importsneeded for type checking must be avoided at runtime. This pattern isdiscouraged; alternatives such as refactoring the code to allow top-levelimports should be preferred.

Imports that are needed only for type annotations can be placed within anifTYPE_CHECKING: block.

3.19.14 Circular Dependencies

Circular dependencies that are caused by typing are code smells. Such code is agood candidate for refactoring. Although technically it is possible to keepcircular dependencies, various build systems will not let you do sobecause each module has to depend on the other.

Replace modules that create circular dependency imports withAny. Set analias with a meaningful name, and use the real type name fromthis module (any attribute ofAny isAny). Alias definitions should beseparated from the last import by one line.

fromtypingimportAnysome_mod=Any# some_mod.py imports this module....defmy_method(self,var:"some_mod.SomeType")->None:...

3.19.15 Generics

When annotating, prefer to specify type parameters forgeneric types in aparameter list; otherwise, the generics’ parameters will be assumed to beAny.

# Yes:defget_names(employee_ids:Sequence[int])->Mapping[int,str]:...
# No:# This is interpreted as get_names(employee_ids: Sequence[Any]) -> Mapping[Any, Any]defget_names(employee_ids:Sequence)->Mapping:...

If the best type parameter for a generic isAny, make it explicit, butremember that in many casesTypeVar might be moreappropriate:

# No:defget_names(employee_ids:Sequence[Any])->Mapping[Any,str]:"""Returns a mapping from employee ID to employee name for given IDs."""
# Yes:_T=TypeVar('_T')defget_names(employee_ids:Sequence[_T])->Mapping[_T,str]:"""Returns a mapping from employee ID to employee name for given IDs."""

4 Parting Words

BE CONSISTENT.

If you’re editing code, take a few minutes to look at the code around you anddetermine its style. If they use_idx suffixes in index variable names, youshould too. If their comments have little boxes of hash marks around them, makeyour comments have little boxes of hash marks around them too.

The point of having style guidelines is to have a common vocabulary of coding sopeople can concentrate on what you’re saying rather than on how you’re sayingit. We present global style rules here so people know the vocabulary, but localstyle is also important. If code you add to a file looks drastically differentfrom the existing code around it, it throws readers out of their rhythm whenthey go to read it.

However, there are limits to consistency. It applies more heavily locally and onchoices unspecified by the global style. Consistency should not generally beused as a justification to do things in an old style without considering thebenefits of the new style, or the tendency of the codebase to converge on newerstyles over time.

This site is open source.Improve this page.

[8]ページ先頭

©2009-2025 Movatter.jp