「通过Docs学Python」(番外)浅谈Python代码规范

本文详细介绍Python编程中的代码规范,涵盖代码格式、命名习惯、注释风格等,旨在提升代码质量和可读性。

点击上方“潜心的Python小屋”关注我们,第一时间推送优质文章。

前言

大家好,我是潜心。这段时间我看过好几位粉丝甚至是我同学(反正也看不到)写的代码,emmm,确实看得让我有点难受。好的代码规范也能体现出一位代码编写者的编程素质。所以潜心准备写一篇番外篇,介绍下Python中的代码规范(分享自己的一些代码编写习惯)。

本文约2.1k字,预计阅读15分钟。

整体代码规范

这部分不知道怎么叙述,通过举例子来说明吧。此处使用「PyCharm」IDE,因为更能凸显一些不规范的习惯。

有些同学的代码可能是这样呈现的:

这些波浪线是不是很难受?不能这样写呀,变量定义、赋值,操作符的「两端需要有空格呀」!其中命名稍微有点问题(这里不作讨论),括号也不需要,改过之后是这样的:

这样是不是更清楚点?除了上述所说,函数中变量赋值时逗号后需要一个空格:

data = pd.read_csv('ml-1m/ratings.dat',
                       sep='::', engine='python',
                       names=['UserId', 'MovieId', 'Rating', 'Timestamp'])

当然上述说的两端需要空格并不适用在为函数的参数赋值时,这里不需要加空格,如下(随便选取的一段代码):

self.MLP_Embedding_User = keras.layers.Embedding(
            input_dim=num_users,
            output_dim=int(layers[0] / 2),
            name='user_embedding',
            embeddings_initializer='random_uniform',
            embeddings_regularizer=regularizers.l2(reg_layers[0])
        )

另外 「导入包与函数或类需要空两行」「函数与函数之间需要空两行」「类中方法之间空一行」「注释#号后需要空一格」,如下:

from utils import *
from evaluate import *


class UserCF:
   """
    User-based collaborative filtering
    """
    def __init__(self, train, W):
        # AAA

    def recommend(self, user):
      
      
def main():

命名

然后是关于命名,包括常量命名、变量命名、函数命名、类命名、方法命名等。

Python需要遵守的基本命名规则为:

  • 命名只能包含字母、数字和下划线,但开头不能以数字命名,如可命名message_1,不可1_message;

  • 命名不能包含空格;

  • 不要将Python关键字、保留字和内置函数名用于命名;

上述是「最基本的命名规范」,遵守这三条规则,至少不会让你的程序因为命名问题报错。

命名准则

接下来潜心会分享一些约定俗成的命名准则,主要遵循这几个要求:

  1. 准确:名字与意义匹配易于区别。

  2. 简洁:命名长度不要过长,要简短;

  3. 明确:一个概念对应一个词,不用双关语;

关于准确,不用多说,得说明这个变量(函数等)的实际意义、作用是什么。

例如:命名用户、物品两个变量,一些同学可能会这样写:

a, b = ['u1', 'u2', 'u3'], ['i1', 'i2', 'i3']
# 或者
yonghu, wupin = ['u1', 'u2', 'u3'], ['i1', 'i2', 'i3']

其实这样命名可能对你的整个代码运行的准确率没有影响,但是你要是以后再回过去看自己代码,或让别人阅读你的代码呢(a,b到底指什么呀)?关于用中文拼音,虽然能达到「准确」的要求,但是潜心不推荐,因为这也太难受了,而且给人一种小白的感觉,今天还看到有公众号粉丝给我发的一个代码,某博客上这样命名(刚好当作反例):

def shuzizhuandaxiejine(data):

emmm,还是希望大家采用英文命名,上述问题我倾向于这样写:

user, item = ['u1', 'u2', 'u3'], ['i1', 'i2', 'i3']

接下来是简洁,潜心不建议用一个很长的英文命名,虽然「准确」,但是太长影响观感,而且有时候会因为其需要不必要的换行。

例如:定义一个基于物品的协同过滤算法,一些同学可能这样写:

class Item_collaborative_filtering:

这样太过冗长,建议这样写:

class ItemCF:

因为CF在推荐领域中,就是指代协同过滤,不需要使用完整的名称,此处需要同学们综合考虑了。

最后是明确,需要在一个Project中规范每个变量的名称,不要在一个函数中使用的变量名称,在另一个函数中又是另一个含义。

例如:在整个协同过滤的算法中,某个函数需要用户的整个列表,某个函数需要某个用户,有同学可能这样写:

def userSimilarity(user):
  
def recommend(user):

这样写是有歧义的,两个user,指代的内容不同。推荐这样写:

def userSimilarity(user):
  
def recommend(u):

或者:

def userSimilarity(user_l):
  
def recommend(user):

上述都是一些结合实际要求的命名,万一这个变量没有什么实际含义呢?这里有些小建议,对于数字,一般会命名为:num1, num2, ...,如果是一个数字列表:nums, arr,字符串:s1, s2,...等。

常用的命名方法

「骆驼式命名法」:正如它的名称所表示的那样,是指混合使用大小写字母来构成变量和函数的名字。函数名中的每一个逻辑断点都有一个大写字母来标记,首字母为小写。例如,下面是分别用骆驼式命名法命名:

def userSimilarity(user):

「下划线命名法」:下划线法是随着C语言的出现流行起来的。例如:

def user_similarity(user):

「帕斯卡(pascal)命名法」:与骆驼命名法类似。只不过骆驼命名法是首字母小写,而帕斯卡命名法是首字母大写,如:

def UserSimilarity(user):

一般我会选择使用下划线命名法。

其他

一些特殊的命名规则:

1、一些全局常量,建议用全部大写来命名:类似MAX_INT

2、类名称首字母建议大写,函数、方法名称建议小写;

3、文件名称建议大写。文件名称在代码中尽量不要重复用到,有时候会出现一些错误(潜心遇到过);

注释

注释在程序中也是非常重要的一部分,虽然它不影响程序的运行,但是可以让其他用户更容易的理解你的思想。注释最好也是用英文,当然中文注释也未尝不可(不推荐主要是有些编码方式会使中文乱码)。这里潜心会通过一个以前写的代码简单介绍下自己的注释习惯。

开头

在每一个Project最开始的地方,潜心都会打上注释,标记编写项目名称、时间以及作者。例如:

"""
Created on Mar 19, 2020

Item-based collaborative filtering

@author: Qianxin
"""

这样是不是一下子觉得自己的代码厉害了起来呢?(时间是提醒你,看看上次是啥时候写的了!!!)

每个类下也会标注这是什么类(这里就偷懒写的比较简单):

class ItemCF:
    """
    Item-based collaborative filtering
    """

类的初始化,第一行注明这是个初始化方法,参数注释有严格的要求,:param后加上参数名,再注明参数的含义。初始化和函数与类的方法注释有所不同(返回值不用写):

    def __init__(self, train, W):
        """
        init
        :param train: train dataset
        :param W: item's similarity matrix
        """
        self.train = train
        self.W = W

函数/方法

其实和初始化注释的方式相同,但是必须要注明「返回值」,不管是否返回。

    def recommend(self, user):
        """
        recommend one user
        :param user: user's ID
        :return:
        """
        rank = dict()
        interacted_items = self.train[user]
        for i, pi in interacted_items.items():
            for j, wj in sorted(self.W[i].items(), key=lambda x: x[1], reverse=True)[:10]:
                ...
        rank = sorted(rank.items(), key=lambda x: x[1], reverse=True)
        return [r[0] for r in rank]

部分注释

如果一个函数过长,你可以将每一部分的作用也可以注明,某些变量也可以添加注释,这里就按照每个人的编程习惯,例如:

def UserSimilarity(train):
    """
    calculate interest similarity between users
    :param train: train dataset
    :return: user's similarity matrix
    """
    # build inverse table for item_users
    item_users = dict()
    ...
    # calculate finial similarity matrix W
    for u, related_users in W.items():
        for v, cuv in related_users.items():
            W[u][v] = cuv / np.sqrt(N[u] * N[v])
    return W

总结

上述是潜心的一些编写代码的经验,如果有什么不对的地方,同学们可以私信我。如果喜欢的话,请给个关注哦!另外潜心也有个 「Python学习交流群」(没人),想要加入的也可以联系我。

往期精彩回顾

「通过Docs学Python」(三)内置类型:文本、集合以及映射

「通过Docs学Python」(二)内置类型:数字与序列

「通过Docs学Python」(一)前言

爬虫基础知识(一)多线程与threading模块

哔哩哔哩爬虫实战----验证码识别

今日头条爬虫实战----爬取图片

爬虫实战(三)----使用百度API获取经纬度/地址

扫码关注更多精彩

我就知道你“在看”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值