首页 > 代码库 > python高级编程之选择好名称:命名指南

python高级编程之选择好名称:命名指南

# # -*- coding: utf-8 -*-

# # python:2.x

# __author__ = ‘Administrator‘

#命名指南

#一组常用的命名规则可以被应用到变量,方法函数和属性上,类和模块的名称在命名空间叫是扮演重要角色的,所以一般有2个模式:觉模式和反模式

#使用has,is前缀命名布尔元素,例如

#当一个元素用来保存布尔值,使用has,is前缀命名布尔元素是一个很好的选择

class DB(object):

    is_connected=False

    has_cache=False

has_1=DB()

print has_1.has_cache

#复数形式命名序列元素

#当一个元素是用来保存一个序列,使用复数形式命名是个好主意,对一些以类似序列的形式输出映射而言,也是可以的

class DN(object):

    connected_user=[‘tarek‘]

    tables={‘cutomer‘:[‘id‘,‘frm‘,‘lat‘]}

 

#用显式全称命名字典

#当一个变量用来保存一个映射时,应该尽可能使用显式名称

perespod_addre={‘appl‘,‘65556‘}

#避免通用名称

#当在代码中不构建一个新的抽象数据类型,如list,dict,sequence等这样的名称是有害的,即使对于局部变量也一样,如下

def comput(data):

    for element in data:

        yield element*12

 

def disup_num(num):

    for num1 in num:

        pass

#避免现有名称,当上下文中名称已经有了是一种坏习惯,会在调试时产生很多混乱

def bad_ct():

    os=1

    import pdb

    pdb.set_trace()

    return os+2

 

#在这个例子中,os名称将被代码遮蔽,内建来自标准程序库模块名都应该被避免,

#尝试创建独特名称,即使它们是上下文的局部变量,对于关键字而言,添加一个后缀下划线避免冲突一种方法,如下

def x(tree,or_=True):

    pass

#class 经常被改成klass或者cls,如下

def funct(klass,*a,**ki):

    return klass(*a,**ki)

print

 

#________

#参数最佳实践

#根据3个简单规则来说明前面的内容

"""

根据迭代设计构建参数

信任参数和测试

小心使用魔法参数*args和**kw

"""

#根据迭代设计构建参数

#当每个函数都有一个固定的,精心设计参数列表,会变的健壮,但是这在第一个版本中不能完成,所以根据迭代设计构建参数,它们应该反映创建该元素所针对使用场景,并且相应地进行演化,如下

#当附加一些参数时,应该尽可能有默认值以避免任何退化

class BD(object):

    def _q(self,q1,q2):

        print ‘_q(2个参数)‘

    def execute(self,q1):

        self._q(q1,‘execute‘)

BD().execute(‘my query‘)

import logging

class BD(object):

    def _q(self,query,types,logger):

        logger(‘song‘)

    def execute(self,a,loggeg=logging.info):

        self._q(a,‘execute‘,logging)

#当一个公共元素的参数必须变化时,将使用一个deprecation进程,后面讲解

#信任参数和测试

#基于python动态类型特性考虑。有些开发人员在函数和方法善使用断言来确定有正确内容,如下:

def division(d,d1):

    assert type(d) in (long,int,float)

    assert type(d1) in (long,int,float)

    return d/d1

#这通常是那些习惯于动态类型并且感觉python中缺少点什么开发人员

#这种检查参数的方法是契约式设计编程风格(design by contract:http://en.wikipedia.org/wiki/design_by_contract)一部分,在这样的设计中,代码在实际运行之前会先检查断言

#主要2个问题

"""

1:dbc代码解释它应该如何使用,导致程序易读性降低

2:可能使代码执行速度变得更慢,因为每次调用都要进行断言

"""

"""

2可以通过执行解释程序时加上-O选项来避免,在这种情况下,所有断言都商贸城 字节码被创建之前从代码中删除,这样检查也就会丢失

在任何情况下,断言都必须小心进行,并且不应该导致python变成一种静态类型语言,唯一使用场景就是保护代码不被无意义的调用.

一个健康的测试驱动开发风格在大部分情况下将提供健壮的基础代码,在这里,功能和单元测试验证了所有创建代码所针对的使用场景

当程序库中的代码被外部元素使用时,建立断言可能是有用的,因为输入数据可能会导致程序结束甚至造成破坏,这在处理数据库或者文件系统代码中是很可能发生的。

另一种庐江是:模糊测试(fuzz testing:en.wikipedia.org/wiki/fuzz_testing),它通过向程序发送随机数据块以检测其弱点,当发现一个新的缺陷时,代码可以相应地被修复,并加上一次新的测试

让我们来关注一个遵循TDD方法,向正确的方向演变并且每当新的缺陷出现时进行调整,从而使健壮性越来越好的代码,当它以正确的方式完成时,测试中的断言列表在程度上变得和预言列表相似

DBC程库,可以在contracts for python(www.wayforward.net/pycontract/)中找到

"""

#小心使用*a,**k魔法参数可能会破坏函数或者方法的健壮性,会使用签名变得模糊,而且代码常常开始不在出现的地方构建小的参数解析器,如下

def f(**k):

    if ‘d‘in k:

        print ‘ok1‘

    else:

        print ‘ok2‘

    print ‘f(**k)是一个字典‘

#当参数列表很长而且很复杂时,那么添加魔法参数是很有诱惑力的,但这通常意味着,它是一个脆弱的函数或者方法,应该被分解或者重构

#当*a被用来处理一系列在函数中以同样方式处理的元素时,要求传入比如iterator之类的唯一容器参数会更好,如下

def s(*a1):#可行

    t1=0

    for a in a1:

        t1+=a

    return t1

def s(a1):#更好

    t1=0

    for a in a1:

        t1+=a

    return t1

#对于**k而言,和8a一样的规则,这样会让方法签名更有意义

def kw(**kw):#可行

    n=kw.get(‘a‘,‘b‘)

    return ‘%s‘%(n)

def kw(a=‘a‘,b=‘b‘,c=‘c‘):

    return a,b,c

#另一种有趣的庐江是创建一个聚焦多个相关参数以提供执行环境容器类,这种结构与8a,**k不同,因为它可以提供工作于数值之上并且能够独立深化内部构件,将它当作参数来使用代码将不必处理其内部构建

#web例子

def log1(reque):#版本1

    return reque.get(‘http‘,‘no url‘)

def log2(re1):#版本2

    print re1.get(‘http‘,‘no url1‘)

    print re1.get(‘http‘,‘no url1‘)

#魔法参数有时候是无法避免的,特别是在元编程时,总的来说,当涉及仅仅位于函数中未知数据时,魔法参数很擅长,如下:

def log(**conte):

    logging.info(str(conte))

 

#类名:必须简明,精确,并足以从中心理解类所完成的工作,常见的一个方法是使用表示其类型或者特性后缀,如:

"""

SQLEngine

MimeTypes

StringWidget

TestCase

"""

#对于基类而言,可以使用一个Base或者Abstract前缀,如下

"""

BaseCookie

AbstractFormatter

"""

#最重要的是要和类特性保持五毒,如:

#SMTP.smtp_send()  命名空间中存在冗余信息

#SMTP.send() 可读性更强,也更易于记忆

 

#模块和名名称

#在模块和名名称中,应该体现出内容用途,这些名称应简短,使用小写字母,不使用下划线,如下

"""

sqlite

postgres

shal

"""

#如果它们实现一个协议,那么通常会使用lib前缀,如下

import smtplib,urllib,telnetlib

#它们在命名空间中也必须保持一致,这样使用起来会更简单,如下

#from widgets.stringwidgets import TextWidget 不好的

#from widgets.strings import TextWidget 好的

#同样,应该始终避免使用与来自标准程序库模块相同名称

#当一个模块变得比较复杂,包含很多类时,创建一个包并将模块元素分到其他模块中是一个好习惯

#__init__模块也可以用来将一些API放回最高级别中,因为它不会影响这些API使用,而且帮助将代码组织为更小的部分,比如foo包中一个模块,如下

#from module1 import f1,f2

#from mudule2 import f3

#允许用户直接导入功能,如下

# from foo import f1

# from foo import f2,f3

# 但是要意识到,这可能会增加循环依赖可能性,__init__模块中添加代码将被实例化,所以要小心使用.

python高级编程之选择好名称:命名指南