Личное резюме - Всеобъемлющие «Спецификации кодирования Python»

задняя часть Python Google Unicode

Цель этой статьи

«Динамический тип — это круто какое-то время, крематорий рефакторинга кода», то есть: динамический язык относительно крут на начальном этапе разработки, но его сложнее поддерживать на более позднем этапе. Как один из динамических языков, Python, естественно, имеет такие недостатки. На самом деле "крематорий" - это не так уж и серьезно, при строгом соблюдении набора спецификаций его тоже можно "рефакторить, это же круто".

Нормы, естественно, очень важны, а в динамических языках они особенно важны (многие люди пишут скрипты на Python, в основном пишу их по своему желанию, что, естественно, сложно потом поддерживать). Так называемые «ставки и кони идут первыми», мы должны проделать достаточно «поверхностной работы» перед написанием кода.

Что не охватывает эта статья

Не делайте: «Документ читает машину». В Pep 8 это было, и не повторим, повторите некоторые из «ниже (мы все знаем)« Содержание », ничего не знаком.

Не верьте авторитету, здесь имеется в виду "Руководство по Python для Google", которое является спецификацией, подходящей для Google, а не спецификацией сообщества. На самом деле, я думаю, что эта спецификация не является полной, и в то же время это всего лишь какой-то «известный» контент, который не рекомендуется.

Не занимайтесь религиозными убеждениями, льстите прагматизму. Например, типичное «импортировать это», мне одному кажется, что это просто куча пустой чепухи? не достигнуто. Каждый раз, когда в различных статьях (недобросовестных маркетинговых статьях, с различными учебными заведениями в качестве основной части) упоминается это, мне становится очень неловко и неловко (написание кода — это очень инженерно и серьезно, зачем заниматься такой метафизикой? ).

Область применения и принципы

  • Python 2.7 — Python 3.x. Хотя официально заявлено, что срок жизни Python 2 — 2020 год, и похоже, что Python 3 сейчас стал мейнстримом. Но одноклассники, устаревший код не убрать, Python 2 еще долго будет существовать. Кроме того, есть ли у Python 3 «убойная функция» по сравнению с Python 2?
  • Создан по образцу PEP 8, тесно объединенный вокруг PEP 8. Любая неофициальная документация предназначена только для справки (аналогично, эта статья тоже своего рода справочная).
  • Не повторяйте то, что уже есть в PEP 8.

Спецификация

[Обязательно + Обязательно] [Выберите инструмент «Статическая проверка» и используйте его строго от начала до конца]

简单来说,就是:
1. Pylint
2. Flake8
3. pytest

一开始就要使用,并且从严使用(发点时间了解这几个工具,带来的收益是无限的,如果你是比较正式的项目的话)。

【Обязательно+】【Множественная запись UT】

其他编程语言,同理。

有一份UT在手,重构起来,心里放心很多。

Python的话,只需要了解unittest就够了,pytest也可以。

【Обязательно】【Кодировка файлов и Юникод】

PS:Следующие пункты могут помочь вам избежать многих скучных проблем с кодированием и декодированием, поэтому я думаю, что это очень важно.

  1. Отступ с 4 пробелами, отключите любые символы вкладок
  2. Исходные файлы используют формат кодировки UTF-8 без спецификации.
  3. Всегда используйте символы новой строки в стиле Unix \n
  4. В заголовке каждого файла py добавьте следующее:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
 

# 只导入 future 空间的这两个特性就够了,其他特性容易造成其他方面的『不兼容』,没有使用的必要性。
from __future__ import (absolute_import, unicode_literals)

所以,你需要了解 editorconfig 这个东西,从根源上统一规范,不符合规范的,直接拒绝 PUSH or MERGE

###【Обязательно】【Имя】

  1. Как назвать класс и функцию, я не буду вдаваться в подробности, просто строго следуйте PEP8, не думайте слишком много.
  2. Глобальные переменные (глобальные переменные, как правило, константы, мы думаем: все глобальные переменные являются константами) всегда должны использовать все заглавные буквы, например:
GLOBAL_PUBLIC = "G1"
_GLOBAL_PRIVATE = "G2"

class Person:
    _GLOBAL_IN_CLASS = 'G3'
    

按照这条要求,其实很多库or开源库,都是不符合要求的。为什么这么强硬呢?
Python中的变量定义,是不分『声明』、『定义』、『初始化』、『赋值』这几个概念的,所以一个
a = 1
如果没有上下文,你是很难确定其作用域的,也很难确定 这到底是初始化还是赋值(a已经存在过),
如果全局变量还不用全大写,带来的麻烦只会更多。

如果始终坚持这个原则,将会给代码的可读性带来极大提升。

[Обязательно] Определите перечисление, всегда добавляйте суффикс Enum; определяйте исключение, всегда добавляйте суффикс исключения; определяйте миксин, всегда добавляйте суффикс миксина, например

class DirectionEnum:
    UP = 1
    DOWN = 2
    
    
class MyException(Exception):
    pass
class MyError(Exception):
    pass
    
class SomeMixin:
    pass

[Обязательно] [Усилить понятие частного]

即:最小知识原则,对外暴露的东西越少越好

翻译成大白话就是:
1. 实例属性,一般定义成private的
2. class,对外提供的方法越少越好
3. module,对外提供的接口越少越好
4. package,对外提供的 module 越少越好

翻译成代码就是:
1. 项目布局
package/
    __init__.py
    _private_mod.py
    public_mod.py    
    
2. 某模块内容
public_mod.py
PUBLIC_GLOBAL = 'G1'
_PRIVATE_GLOBAL = 'G2'
class _Class:
    pass
class PublicClass:
    _PRIVATE_GLOBAL = 'G3'
    
    def __init__(self, name,age):
        self._name = name
        self._age = age
    def public_method(self):
        pass
    def _private(self):
        pass
        

所有东西,一开始就要定义成私有的,等到确实需要开放访问了,才开放出去。

[Обязательно и важно] [Сосредоточьтесь на сложности общедоступных интерфейсов]

最好的接口是这样的,调用者无脑使用
def interface():
    pass
    
次等接口是这样的
def interface(param1):
    pass
    
次次等接口是这样的
def interface(p1, p2):
    pass

最大忍受限度的接口是这样的
def interface(p1, p2, p3='SOME DEFAULT'):
    pass
def interface(p1, *args):
    pass
    
不可接受的接口是这样的
def interface(p1, p2, **kwargs):
    pass

令人无语的接口是这样的
def interface(*args, **kwargs):  
# 尽量不要使用 **kwargs, 某些流行库有这样的毛病,我是觉得:极大地增加了调用者的心理负担,反映了接口设计者的懒惰
    pass
    
一直觉得,**kwargs只适用于极少数明确的场合,并且需要辅以很明确的文档说明(解释为什么要使用),然而现实是,这个
特性已经被大家滥用了,有必要单独说明之。

PS: Я всегда чувствую, что злоупотребление API **kwargs — это почти не очень хороший API, который незаметно увеличивает психологическую нагрузку.

[Рекомендация] [Создавайте пространства имен с помощью пакетов, а не модулей]

【Рекомендация】【Знайте следующее】

__init__.py 的作用

__main__.py 的作用

if __name__ == '__main__': 的作用

Python的命名空间加载机制,即:sys.path sys.modules 的内容

[рекомендуется] [разумная структура каталогов дизайн-проекта]

如果是使用某种框架(如Django),那么按照框架的规范来;如果是“非框架”项目,则按照如下结构

project
    project/
        __init__.py
        core/
        utils/
        constants/
        
        
        __main__.py
        
    tests/
    docs/
    examples/
    README.md
    .pylintrc
    .flake8