如何参与python的开源项目(上)

最近给apache 下的libcloud 项目提交了几个bug和patch,然后看到了一遍不错的指引,详细包括了编码规范及提交工作流程。

见链接:https://libcloud.readthedocs.io/en/latest/development.html#contributing-bigger-changes

翻译一下。

  • 代码风格

遵循PEP8规范

使用四个空格缩紧

每行最长为79个字符

确保已经编辑好的文件不包含任何尾随的空格

可以通过flake8检测代码规范flake8 libcloud/edited_file.py(单个文件) 和 tox -e lint(整个项目)


最重要的是,遵循你编辑的文件样式风格和现有代码中的样式风格保持一致。


  • 预提交钩子检测

为了更容易遵守风格指南,项目提供了一个git预提交钩子,它会自动检查修改后的Python文件是否违反风格指南。

在项目代码的根目录下安装:

ln -s contrib/pre-commit.sh .git/hooks/pre-commit
安装好之后,这个工具会在提交之前会自动检测代码的风格,如果违反代码风格,这个提交将会被丢弃。


  • 代码约束
  •  导入模块顺序

标准库

第三方库

本地库

例子,每一类模块用空行区分:

import sys
import base64

import paramiko

from libcloud.compute.base import Node, NodeDriver
from libcloud.compute.providers import Provider

  • 函数和方法顺序

模块中的函数和类中的方法应按遵循以下顺序:
  1. “公共”函数/方法
  2. “私有”函数/方法(下划线为前缀的方法)
  3. “内部”方法(前缀和后缀双下划线)

例子:

class Unicorn(object):
    def __init__(self, name='fluffy'):
        self._name = name

    def make_a_rainbow(self):
        pass

    def _get_rainbow_colors(self):
        pass

    def __eq__(self, other):
        return self.name == other.name

驱动程序类上的方法应按遵循以下顺序:

  1. 标准api的方法
  2. 扩展方法
  3. “私有”方法(下划线为前缀的方法)
  4. “内部”方法(前缀和后缀双下划线)

功能相似的方法应该被划分在一块,并一个接一个的定义

例子:

class MyDriver(object):
    def __init__(self):
        pass

    def list_nodes(self):
        pass

    def list_images(self):
        pass

    def create_node(self):
        pass

    def reboot_node(self):
        pass

    def ex_create_image(self):
        pass

    def _to_nodes(self):
        pass

    def _to_node(self):
        pass

    def _to_images(self):
        pass

    def _to_image(self):
        pass

遵循这种顺序能够使得阅读和生产api文档更容易,而且可读性更强。

  • 优先使用关键字代替常规参数

为了更好的可读性和理解的代码,关键字比常规参数优先。

# Good
some_method(public_ips=public_ips, private_ips=private_ips)
# Bad
some_method(public_ips, private_ips)

  • 不要滥用** kwargs

应该始终在函数或方法签名中显式声明参数,并且只有在有有效的用例时才使用** kwargs和* args。

使用** kwargs某些时候是违反Python的“显式优于隐式”的,并且可能使API变得含糊不清。最重要的是,它使许多有用的东西,如程序性API内省变得不可靠。

可以用添加默认参数替代。

# Good
def my_method(self, name, description=None, public_ips=None):
    pass

# Bad
def my_method(self, name, **kwargs):
    description = kwargs.get('description', None)
    public_ips = kwargs.get('public_ips', None)
 
     

  • 返回字典时,记录其结构

Python的动态性非常有用,但是如果以错误的方式使用它,它也可能使得API消费者很难理解正在发生什么以及返回什么类型的值。

如果有一个函数或一个方法返回一个字典,确保在文档里记录返回的字典包含哪些键。

  • 在检查是否提供或定义变量时,优先使用“is not None”

检测一个变量的存在性,优先使用if foo is not None替代if foo。

如果你使用if foo的防水,很容易犯一个错误,就是一个有效的值也可以是false(例如数字0)。

例子

class SomeClass(object):
    def some_method(self, domain=None):
        params = {}

        if domain is not None:
            params['Domain'] = domain




你可能感兴趣的:(python)