Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

10 Commits

Repository files navigation

Python Style Guide

Table of Contents

  1. Inports
  2. Indentation
  3. Techniques

Inports

  • 1.1 Split imports into 3 categories (stdlib, 3rdparty, internal imports), relative imports should be the last. Try to keep them sorted.

    importdatetimeimportloggingfromdjango.utilsimporttimezonefromdjango.utils.translationimportugettext_lazyas_fromdjango.confimportsettingsfromdjango_states.machineimportStateMachine, StateDefinition, StateGroup, StateTransitionfromdjango_states.exceptionsimportTransitionValidationErrorfromourapp.notifications.handlersimportNOTIFICATION_METHODfromourapp.notificationsimportnotifiersfromourapp.module_a.providerimportTrustedfromourapp.activation.modelsimportXOrderfromourapp.porting.utilsimportget_closest_wish_datefrom .modelsimportInportfrom .utilsimportadd_inport_s3

  • 1.2 Use imports for packages and modules only, if it is possible.

    importdatetime# never: from datetime import datetime or similarimportlogging# never: from logging import getLoggerimportmock# never from mock import Mockimportrandomimportuuidimportbson# never from bson import ObjectIdfromdjango.utilsimporttimezone# never: from django.utils.timezone import now

  • 1.3 If import exceeded line length limit, format it like that:

    fromourapp.porting.tasksimport (
    task_a,
    task_b,
    task_c, # <- comma here
    )

Indentation

  • 2.1function calls

    abc=qwe(dsadsa(product.to_dict(), cls=DecimalEncoder, mimetype='application/json')) # badabc=qwe(dsadsa(product.to_dict(), cls=DecimalEncoder,
    mimetype='application/json')) # badabc=qwe(dsadsa(product.to_dict(),
    cls=DecimalEncoder,
    mimetype='application/json')) # badabc=qwe(dsadsa(
    product.to_dict(),
    cls=DecimalEncoder,
    mimetype='application/json', # <- comma here
    )) # OKabc=qwe(
    dsadsa(
    product.to_dict(),
    cls=DecimalEncoder,
    mimetype='application/json', # <- comma here
    )
    ) # could be too# especially when qwe has one aditional keyword parameter:abc=qwe(
    dsadsa(
    product.to_dict(),
    cls=DecimalEncoder,
    mimetype='application/json', # <- comma here
    ), # <- comma heredupa=2, # <- comma here
    ) # OK

  • 2.2dict class

    # badabc=dict(abc=2, cde=5, mama='tata', tata='mama', raz=1, dwa=2)
    # badabc=dict(abc=2, cde=5, mama='tata',
    tata='mama', raz=1, dwa=2)
    # bad abc=dict(
    abc=2, cde=5, mama='tata',
    tata='mama', raz=1, dwa=2
    )
    # badabc=dict(
    abc=2, cde=5, mama='tata',
    tata='mama', raz=1, dwa=2,
    )
    # goodabc=dict(
    abc=2,
    cde=5,
    mama='tata',
    tata='mama',
    raz=1,
    dwa=2, # <- comma here !
    ) 

  • 2.3dict curly brackets

    # badabc= {'abc': 2, 'cde': 5, 'mama': 'tata', 'tata': 'mama', 'raz': 1, 'dwa': 2}
    # badabc= {'abc': 2, 'cde': 5, 'mama': 'tata',
    'tata': 'mama', 'raz': 1, 'dwa': 2}
    # bad abc= {
    'abc': 2, 'cde': 5, 'mama': 'tata',
    'tata': 'mama', 'raz': 1, 'dwa': 2
    }
    # badabc= {
    'abc': 2, 'cde': 5, 'mama': 'tata',
    'tata': 'mama', 'raz': 1, 'dwa': 2,
    }
    # goodabc= {
    'abc': 2,
    'cde': 5,
    'mama': 'tata',
    'tata': 'mama',
    'raz': 1,
    'dwa': 2, # <- comma here !
    }

  • 2.4func call and dicts

    abc=abc({
    'a': 1,
    'b': 3,
    'c': 4, # <- comma here !
    })
    abc=abc(dict(
    a=1,
    b=2,
    c=3, # <- comma here !
    ))
    nokaut_api_params=urllib.urlencode({
    'key': str(nokaut_key),
    'keyword': str(keyword),
    'format': 'xml',
    'method': 'nokaut.Product.getByKeyword',
    'sort_direction': 'price_asc',
    'returnType': 'full',
    'limit': '1', # <- comma here !
    })

  • 2.5list comprehension

    # baddata= [model_fieldforform_field, model_fieldinfieldsifform_fieldinform]
    # baddata= [model_fieldforform_field, model_fieldinfieldsifform_fieldinform
    ]
    # gooddata= [
    model_fieldforform_field, model_fieldinfieldsifform_fieldinform
    ]
    # good (if exceeding line length limit)data= [
    model_fieldforform_field, model_fieldinfieldsifform_fieldinform
    ]

  • 2.6dict comprehension

    # baddata= {model_field: form[form_field].dataforform_field, model_fieldinfieldsifform_fieldinform}
    # gooddata= {
    model_field: form[form_field].dataforform_field, model_fieldinfieldsifform_fieldinform
    }
    # good (if exceeding line length limit)data= {
    model_field: form[form_field].dataforform_field, model_fieldinfieldsifform_fieldinform
    }

  • 2.7if statement if conditions are too long, store their result in variable with meaningful name

    # badifabcisNoneandbisTrueandc=='mama' \
    andx!=1orcin ('mama', 'tata') \
    orbabcia.age>100: # checks if thing should be done# do something big# badif (abcisNoneandbisTrueandc=='mama'andx!=1orcin ('mama', 'tata')
    orbabcia.age>100): # checks if thing should be done# do something big# goodshould_be_done= ( # no comment needed !abcisNoneandbisTrueandc=='mama'andx!=1orcin ('mama', 'tata') orbabcia.age>100
    )
    ifshould_be_done:
    # do something big

  • 2.8slashes never use them

    # bad:defx():
    a_identity=self.aidentityconfirm_set.filter(uuid=self.id_at_provider).first()
    returna_identity.get_person_who_registed_y().get_full_name()\
    ifa_identityanda_identity.state=="confirmed"else"A identity is not confirmed yet"# good:defx():
    a_identity=self.aidentityconfirm_set.filter(uuid=self.id_at_provider).first()
    ifa_identityanda_identity.state=="confirmed":
    returna_identity.get_person_who_registed_y().get_full_name()
    else:
    return"A identity is not confirmed yet"# there is one exception when you can use slashes, when using chaining methods, examples:# django ORM:posts=Post.objects.filter(blog__id=x)\
    .filter(created_at__gt=y)\
    .filter(desc__contains=z)\
    .order_by('created_at')
    # Google App Engine NDBgreetings=Greeting.query_book(ancestor_key)\
    .filter(Greeting.userid>=40)\
    .filter(Greeting.userid<100)\
    .fetch(self.GREETINGS_PER_PAGE)
    # SQLAlchemyfiles=File.query.filter(File.used.is_(False))\
    .filter(File.modified<daysago2)\
    .yield_per(10)
    # mongoalchemyplace=session.query(Places).filter_by(loc=a)\
    .filter(created_at=b)\
    .descending('created_at').first()

  • 2.9Single quotes vs double quotes Use double quotes around strings that are natural language messages and single quotes for small symbol-like strings, for example:

    LIGHT_MESSAGES= {
    'english': "There are 3 lights.",
    'pirate': "Arr! Thar be 3 lights."
    }
    deflights_message(language, number_of_lights):
    """Return a language-appropriate string reporting the light count."""returnLIGHT_MESSAGES[language]
    defis_pirate(message):
    """Return True if the given message sounds piratical."""returnre.search(r"(?i)(arr|avast|yohoho)!", message) isnotNone

    ref: http://stackoverflow.com/a/56190

Techniques

  • 3.1Bail early is idiomatic coding style.
# BAD, really baddefbad_method(a):
b=one(a)
ifb.isgood():
c=two(b)
ifc.isok():
d=three(c)
ifd.hasX():
returndelse:
raiseNoXErrorelse:
raiseNotOKError# GOOD, more clear, more obvious defgood_method(a):
b=one(a)
ifnotb.isgood():
returnc=two(b)
ifnotc.isok()
raiseNotOKErrord=three(c)
ifnotd.hasX():
raiseNoXErrorreturnd

About

Python Style Guide

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors