Python 进阶
看了之前写的稍微大规模一些的python代码,想改但是无处入手,深觉自己代码欠缺规范性,设计模式也没咋好好学过
从几个方面重新磨一下刀
1.编辑器
VSCODE: 自带高亮,代码补全,自带终端,可以在左下角调整python版本
VSCODE下启用Python插件: A Visual Studio Code extension with rich support for the Python language (for all actively supported versions of the language: 2.7, >=3.5), including features such as IntelliSense, linting, debugging, code navigation, code formatting, Jupyter notebook support, refactoring, variable explorer, test explorer, snippets, and more!
IntelliSense: 智能补全,和vscode自己的补全相比,支持常见类和自定义类的内容补全。vscode的补全只是把上下文中出现过的进行补全。
debugging: 没有Python扩展包,是没有python debug环境的。
-
IntelliSense: Edit your code with auto-completion, code navigation, syntax checking and more
-
Linting: Get additional code analysis with Pylint, Flake8 and more, 代码检查,函数提示,
-
Code formatting: Format your code with black, autopep or yapf, https://www.cnblogs.com/bonelee/p/11045196.html python的formatting没什么用
-
Debugging: Debug your Python scripts, web apps, remote or multi-threaded processes 断点,单步调试很友好
-
Testing: Run and debug tests through the Test Explorer with unittest, pytest or nose
-
Jupyter Notebooks: Define and run code cells, render plots, visualize variables through the variable explorer and more,要在对应环境下,安装一次jupyter。
-
Environments: Automatically activate and switch between virtualenv, venv, pipenv, conda and pyenv environments
-
Refactoring: Restructure your Python code with variable extraction, method extraction and import sorting
其它扩展包,待续
转自https://zhuanlan.zhihu.com/p/94634073
Python语言规范
- 导入包:使用模块全路径来导入包,这样能够避免模块名称相同而造成的冲突
- python 编写一个包,https://blog.csdn.net/destinyuan/article/details/51704935
- 异常处理:首先,
raise
抛出异常抛出异常时应该使用已有的异常类或者自定义异常类,例如,raise MyException("Error message")
,避免抛出一串不知所云的字符串,例如,raise "Error message"
。其次,用except
捕获异常时避免使用Exception
这类泛泛的异常。以上两点主要为了帮助后期调试,能够清楚抛出的什么类型的异常,捕获了什么样的错误,有助于调试。 - 全局变量:尽量避免使用全局变量,可以用类变量替代。
- 列表推导:在简单的情况下鼓励使用列表推导式,复杂的情况下避免使用列表推导式,难以阅读,例如,下方,映射表达式, for语句, 过滤器表达式中简单的情形可以用一行列表推导式代替多行代码。
result = []
for x in range(10):
result.append(x * x)
result = [x ** 2 for x in range(10)]
- 生成器:生成器可以有效的节省内存占用情况,可以按需使用生成器。
- 默认参数值:定义一个函数式,我们为了应对某些特例情况而添加几个参数,但是大多数情况下是用不到的,我们可以采用默认参数值的方式应对这些特例调用问题,这里需要注意,默认参数值不要使用可变对象,例如,列表、字典等。
- True/False的求值:尽量的使用隐式false,在Python中把所有的“空”值,例如,0、None、[]、{}都被认为是false,我们在获取这些返回值时可以用隐式的false,例如,返回的
foo
是一个空列表,我们可以用if foo:
来判断它是否为“空”,而不是if foo==[]:
,这样不仅更加易读,而且能够避免犯错。 - 过时的语言特性:在很多代码里面习惯于使用filter、map、reduce这类语言特性,尽可能使用列表推导或者for循环替代。
以上介绍的是Python在语言方面的规范,也就是说不用这种方式也可以同样实现对应的功能,但是通过上述语言规范能够更多的避免细微之处带来的错误,下面就来介绍一下Python风格规范。
文档字符串:函数,类里面第一个双括号包含的字符串,https://www.zhihu.com/question/263349308
最顶上的docstring介绍了我们应该怎么使用这个函数,包括参数是什么,返回类型是什么,返回的值是怎样的等等。这里的docstring完全没有提到这个函数是如何实现的。
python 开头执行的#!/usr/bin/python3,选择解释器,选择编码方式,#coding:utf-8
这两个在我现在的编程过程里基本都不需要了,也是进步吧
https://www.jianshu.com/p/400c612381dd
https://www.jianshu.com/p/e57631b827d0
python 建立一个库/模块
第一行的文档字符串,对整个库/模块而言,
'doc of a test module' #文档字符串
__author__ = 'XuZhiyuan'
#写入author
https://blog.csdn.net/destinyuan/article/details/51698789
Python中第三方模块的安装
这段没咋看懂,这几个模块管理工具的使用
https://blog.csdn.net/destinyuan/article/details/51698253
自定义模块的import
https://blog.csdn.net/destinyuan/article/details/45640447
模块与包
当代码越来越多的时候,将所有的代码放入一个.py
文件中会显得难以维护。解决办法则是代码分拆入不同的.py
文件中,形成不同模块,这样做还能使得同名变量互不影响,需要注意的是,模块名不应与系统内置函数重名。
同时,不同的.py
文件也可能同名,这时候就可以考虑将其放入不同的文件夹中,形成不同的包,防止同名模块的影响。
在python中一个文件可以被看成一个独立模块,而包对应着文件夹。模块把python代码分成一些有组织的代码段,通过导入的方式实现代码重用;包将有联系的模块组织在一起,有效避免模块名称冲突问题,让应用组织结构更加清晰。区别包和文件夹的重要特征就是包文件夹内每一层目录都有初始化文件__init__.py
!
__init__.py
可以是空文件,也可以有Python代码,因为__init__.py
本身就是一个模块,而它的模块名就是包的名称!
所以import arcpy
的时候,arcpy
是包的名称,实际上导入的是这个包文件夹下面的__init__.py
文件。
建立包并导入
https://blog.csdn.net/destinyuan/article/details/51704935
PyTHON 语言规范
https://zhuanlan.zhihu.com/p/94634073
- 导入包:使用模块全路径来导入包,这样能够避免模块名称相同而造成的冲突 #不知道啥意思
- 异常处理:首先,
raise
抛出异常抛出异常时应该使用已有的异常类或者自定义异常类,例如,raise MyException("Error message")
,避免抛出一串不知所云的字符串,例如,raise "Error message"
。其次,用except
捕获异常时避免使用Exception
这类泛泛的异常。以上两点主要为了帮助后期调试,能够清楚抛出的什么类型的异常,捕获了什么样的错误,有助于调试。 - 全局变量:尽量避免使用全局变量,可以用类变量替代。
- 列表推导:在简单的情况下鼓励使用列表推导式,复杂的情况下避免使用列表推导式,难以阅读,例如,下方,映射表达式, for语句, 过滤器表达式中简单的情形可以用一行列表推导式代替多行代码。
- 生成器:生成器可以有效的节省内存占用情况,可以按需使用生成器。
- 默认参数值:定义一个函数式,我们为了应对某些特例情况而添加几个参数,但是大多数情况下是用不到的,我们可以采用默认参数值的方式应对这些特例调用问题,这里需要注意,默认参数值不要使用可变对象,例如,列表、字典等。
- True/False的求值:尽量的使用隐式false,在Python中把所有的“空”值,例如,0、None、[]、{}都被认为是false,我们在获取这些返回值时可以用隐式的false,例如,返回的
foo
是一个空列表,我们可以用if foo:
来判断它是否为“空”,而不是if foo==[]:
,这样不仅更加易读,而且能够避免犯错。 - 过时的语言特性:在很多代码里面习惯于使用filter、map、reduce这类语言特性,尽可能使用列表推导或者for循环替代。
python 代码风格
https://zhuanlan.zhihu.com/p/149492180
1.行长度不超过80,使用括号跳行
2.括号的宁缺毋滥:不要在返回语句或条件语句中使用括号
3.缩进:空格是首选的缩进方法。制表符应仅用于与已经使用制表符缩进的代码保持一致.Python 3不允许混合使用制表符和空格进行缩进.
老子一直是tab,怎么了嘛。(但是PEP8参考一下就好了,tab在许多IDE是可以转为空格的,pycharm一直没用过,范洪昌说是可以的
不同的系统,编辑器对于TAB的解释是不同的,tab所占的长度不同。但是无所谓啊,功能应该是不影响的,老子宁愿用了tab最后再翻译成空格,也不要写的时候用四个空格。
4.空行:顶级定义之间空两行,两个类,两个函数。方法定义之间空行,两个类方法,类和第一个方法
5.空格:在二元操作符两边都加上一个空格, 比如赋值(=), 比较(==, <, >, !=, <>, <=, >=, in, not in, is, is not), 布尔(and, or, not). 至于算术操作符两边的空格该如何使用, 需要你自己好好判断. 不过两侧务必要保持一致.
6.当'='用于指示关键字参数或默认参数值时, 不要在其两侧使用空格.
yes:
def complex(real, imag=0.0): return magic(r=real, i=imag)
no:
def complex(real, imag = 0.0): return magic(r = real, i = imag)
7.如果一个类不继承自其它类, 就显式的从object继承. 嵌套类也一样.
继承自 object
是为了使属性(properties)正常工作, 并且这样可以保护你的代码, 使其不受Python 3000的一个特殊的潜在不兼容性影响. 这样做也定义了一些特殊的方法, 这些方法实现了对象的默认语义, 包括 __new__, __init__, __delattr__, __getattribute__, __setattr__, __hash__, __repr__, and __str__
.
感觉没什么差别,继承或者不继承自object,也都有这些属性,无非是空的
8.避免在循环中用+和+=操作符来累加字符串. 由于字符串是不可变的, 这样做会创建不必要的临时对象, 并且导致二次方而不是线性的运行时间. 作为替代方案, 你可以将每个子串加入列表, 然后在循环结束后用 .join
连接列表. (也可以将每个子串写入一个 cStringIO.StringIO
缓存中.)
9.
导入总应该放在文件顶部, 位于模块注释和文档字符串之后, 模块全局变量和常量之前. 导入应该按照从最通用到最不通用的顺序分组:
- 标准库导入
- 第三方库导入
- 应用程序指定导入
使用完整路径导入
import foo
from foo import bar
from foo.bar import baz
from foo.bar import Quux
from Foob import ar
10.访问控制
在Python中, 对于琐碎又不太重要的访问函数, 你应该直接使用公有变量来取代它们, 这样可以避免额外的函数调用开销. 当添加更多功能时, 你可以用属性(property)来保持语法的一致性.
(译者注: 重视封装的面向对象程序员看到这个可能会很反感, 因为他们一直被教育: 所有成员变量都必须是私有的! 其实, 那真的是有点麻烦啊. 试着去接受Pythonic哲学吧)
另一方面, 如果访问更复杂, 或者变量的访问开销很显著, 那么你应该使用像 get_foo()
和 set_foo()
这样的函数调用. 如果之前的代码行为允许通过属性(property)访问 , 那么就不要将新的访问函数与属性绑定. 这样, 任何试图通过老方法访问变量的代码就没法运行, 使用者也就会意识到复杂性发生了变化.
11. 命名:
应该避免的名称
- 单字符名称, 除了计数器和迭代器.
- 包/模块名中的连字符(-)
- 双下划线开头并结尾的名称(Python保留, 例如__init__)
命名约定
- 所谓"内部(Internal)"表示仅模块内可用, 或者, 在类内是保护或私有的.
- 用单下划线(_)开头表示模块变量或函数是protected的(使用import * from时不会包含).
- 用双下划线(__)开头的实例变量或方法表示类内私有.
- 将相关的类和顶级函数放在同一个模块里. 不像Java, 没必要限制一个类一个模块.
- 对类名使用大写字母开头的单词(如CapWords, 即Pascal风格), 但是模块名应该用小写加下划线的方式(如lower_with_under.py). 尽管已经有很多现存的模块使用类似于CapWords.py这样的命名, 但现在已经不鼓励这样做, 因为如果模块名碰巧和类名一致, 这会让人困扰.
命名:第一、模块名、包名称、方法名、函数名、实例变量名、函数参数名、局部变量名这些应该使用小写字母加下划线的方式,例如,function_name
;第二、类名、自定义异常名,应该采用驼峰的命名方式,例如,ClassName;第三、全局变量名应该使用大写字母加下划线的方式,例如,GLOBAL_VAL_NAME。
- 生成器:生成器可以有效的节省内存占用情况,可以按需使用生成器。
- 默认参数值:定义一个函数式,我们为了应对某些特例情况而添加几个参数,但是大多数情况下是用不到的,我们可以采用默认参数值的方式应对这些特例调用问题,这里需要注意,默认参数值不要使用可变对象,例如,列表、字典等。
- True/False的求值:尽量的使用隐式false,在Python中把所有的“空”值,例如,0、None、[]、{}都被认为是false,我们在获取这些返回值时可以用隐式的false,例如,返回的
foo
是一个空列表,我们可以用if foo:
来判断它是否为“空”,而不是if foo==[]:
,这样不仅更加易读,而且能够避免犯错。 - 过时的语言特性:在很多代码里面习惯于使用filter、map、reduce这类语言特性,尽可能使用列表推导或者for循环替代。