《Python Enhancement Proposal #8》8号Python增强提案。
空白:①4个空格代表tab ②每行<=79字符 ③分行后加4个空格 ④类中方法空1行,方法和类空2行
命名:①函数、变量、属性用小写字母和下划线组成 ②受保护用单下划线,私有用双下划线 ③类与异常用驼峰 ④模块级别常量用全大写 ⑤类中实例方法首个参数是self,表示改对象;类方法的首个参数是cls,表示该类。
表达式和语句:①not不要放在表达式前面 ② 采用if not list 判断列表是否为空③import放开头且使用绝对路劲引用(但可以form . import models)④import顺序按照标准库、第三方模块库、自用模块导入,每部分按字母顺序排列。
isinstance(obj, class)判断class类型是否是obj的(父)类
str.encode(‘utf-8’)转变为bytes类型 bytes.decode(‘utf-8’)转变为str类型
在读写文件中,默认是’utf-8’,如果使用二进制必须加上‘b’
python3 bytes是8位值的序列,str是包含Unicode字符序列。
python2 str是8位值的序列,unicode是包含Unicode字符序列。若str只包含7位ASCII,可以使用相关操作同时使用。
repr(obj),将obj对象转换成字符串类型
or左边表达式为真则用左边的,否则用右边的 a = False or ‘1’ # a=1
if/else表达式 a = x if x>y else y
assert 表达式, 当表达式等于False时,抛出AssertionError
start或end索引越界也不会出问题
同时指定start、end和stride会导致代码难以阅读,stride尽量使用正值。
可考虑使用itertools模块中的islice。(第46条:使用内置算法与数据结构:)
it = (x for x in range(20000))
next(it)
两个生成器可以串起来用,产生连锁反应。
else后面的代码是在try顺利完成后才运行。
except用法
except ZeroDivisionError as e:
raise ValueError('dsa') from e
用nonlocal语句
nonlocal与global相互补充,nonlocal修改闭包外那个作用域变量,global修改模块作用域的变量
也可以用列表、字典、集合来取代,这样作用域会自动向外搜索
多用生成器,可转list。生成器⊆迭代器
注意生成器只能遍历一次!如果重复迭代,第二次不会报错,会产生一个空列表。解决办法:直接传入迭代器函数进去。
迭代器其实就是fun.__ iter __这个特殊方法
*arg 可变长,转变为元组
**kwargs 字典
也可用默认值代替*arg
参数中有默认值,函数被反复调用,默认值只会产生一次。解决办法用None
def gen(bad={}):
return bad
def main():
f1 = gen()
f1['1'] = 1
f2 = gen()
f2['2'] = 3
print(f1) # {'1': 1, '2': 3}
print(f2) # {'1': 1, '2': 3}
namedtuple
Grade = collections.namedtuple('Grade', ('score', 'weight'))
a = Grade(100, 0.2) # Grade(score=100, weight=0.2) 可迭代 a.score
如果类太复杂,可以拆成多个类。如:Gradebook->Student->Subject
字典初始化定义
res = collections.defaultdict(fun, dict)
# fun函数返回的是字典初始化值
assert 条件,如果条件为false,则程序报错
多态:多种状态,接口的多种不同实现方式。写出通用代码。
定义公共基类、继承
class InputData:
def read(self):
raise NotImplementedError
class PathInputData(InputData):
def __init__(self, path):
super().__init__()
self.path = path
def read(self):
print(self.path)
return 0
尽量避开多重继承
若一定使用,则用mix-in类。(额~其实这里我想不出有什么用)
protect属性是单下划线,private是双下划线。
@property将protect属性写成函数访问
如果要访问私有属性,则继承A类,然后obj._A__private可访问,因为python会对私有属性的名称做变换
多用protect属性,少用private,当子类不受控制时,才考虑用private
getattr当对象找不到对应属性时,会在这里找
def __getattr__(self, item):
value = '123'
setattr(self, item, value) # 设置这个值
return value
getattribute无论属性是否在__ dict__中,都会触发该函数,如果没有该属性会raise AttributeError.调用该方法一定要super(),否则会递归的一直调用。
33-35书上的内容过旧
第46条:使用内置算法与数据结构