Ptyhon编程规范

编码

所有的 Python 脚本文件都应在文件头标上 # -*- coding:utf-8 -*-
设置编辑器,默认保存为 utf-8 格式。

注释

业界普遍认同 Python 的注释分为两种的概念,一种是由 # 开头的“真正的”注释,另一种是 docstrings。
前者表明为何选择当前实现以及这种实现的原理和难点,
后者表明如何使用这个包、模块、类、函数(方法),甚至包括使用示例和单元测试。

坚持适当注释原则
对不存在技术难点的代码坚持不注释,对存在技术难点的代码必须注释。
但与注释不同,推荐对每一个包、模块、类、函数(方法)写 docstrings,除非代码一目了然,非常简单。

缩进

Python 依赖缩进来确定代码块的层次,行首空白符主要有两种:tab 和空格,但严禁两者混用。
如果使用 tab 缩进,设定 tab 为 4 个空格。

推荐使用 4 个空格的 tab 进行缩进。

空格

空格在 Python 代码中是有意义的,因为 Python 的语法依赖于缩进,在行首的空格称为前导空格。
在这一节不讨论前导空格相关的内容,只讨论非前导空格。

非前导空格在 Python 代码中没有意义,但适当地加入非前导空格可以增进代码的可读性。

  1. 在二元算术、逻辑运算符前后加空格:如 a = b + c
  2. 在一元前缀运算符后不加空格,如 if !flg: pass
  3. “:”用在行尾时前后皆不加空格,如分枝、循环、函数和类定义语言;用在非行尾时两端加空格,如 dict 对象的定义 d = {‘key’ : ’value’}
  4. 括号(含圆括号、方括号和花括号)前后不加空格,如 do_something(arg1, arg2),而不是 do_something( arg1, arg2 )
  5. 逗号后面加一个空格,前面不加空格;

空行

适当的空行有利于增加代码的可读性,加空行可以参考如下几个准则:

  1. 在类、函数的定义间加空行;
  2. 在 import 不同种类的模块间加工行;
  3. 在函数中的逻辑段落间加空行,即把相关的代码紧凑写在一起,作为一个逻辑段落,段落间以空行分隔;

断行

尽管现在的宽屏显示器已经可以单屏显示超过 256 列字符,但本规范仍然坚持行的最大长度不得超过 78 个字符的标准。
折叠长行的方法有以下几种方法:

  1. 为长变量名换一个短名,如:

    this.is.a.very.long.variable_name = this.is.another.long.variable_name

应改为:

variable_name1 = this.is.a.very.long.variable_name
variable_name2 = this.is.another.variable_name
variable_name1 = variable_name2s
  1. 在括号(包括圆括号、方括号和花括号)内换行,如:

    class Edit(CBase):
    def init(self, parent, width,
    font = FONT, color = BLACK, pos = POS, style = 0):

或:

very_very_very_long_variable_name = Edit(parent, /
                                width, /
                                font, /
                                color, /
                                pos)
                                

如果行长到连第一个括号内的参数都放不下,则每个元素都单独占一行:

very_very_very_long_variable_name = ui.widgets.Edit( /
                                panrent, /
                                width, /
                                font, /
                                color, /
                                pos)
                                
  1. 在长行加入续行符强行断行,断行的位置应在操作符前,且换行后多一个缩进,
    以使维护人员看代码的时候看到代码行首即可判定这里存在换行,如:

    if color == WHITE or color == BLACK /
    or color == BLUE: # 注意 or 操作符在新行的行首而不是旧行的行尾
    do_something(color);

命名

一致的命名可以给开发人员减少许多麻烦,而恰如其分的命名则可以大幅提高代码的可读性,降低维护成本。

常量

常量名所有字母大写,由下划线连接各个单词,如

WHITE = 0XFFFFFF
THIS_IS_A_CONSTANT = 1

变量

变量名全部小写,由下划线连接各个单词,如

color = WHITE
this_is_a_variable = 1

不论是类成员变量还是全局变量,均不使用 m 或 g 前缀。
私有类成员使用单一下划线前缀标识,多定义公开成员,少定义私有成员。

变量名不应带有类型信息,因为 Python 是动态类型语言。
如 iValue、names_list、dict_obj 等都是不好的命名。

函数

函数名的命名规则与变量名相同。

类名单词首字母大写,不使用下划线连接单词,也不加入 C、T 等前缀。如:

class ThisIsAClass(object):
    passs

模块

模块名全部小写,对于包内使用的模块,可以加一个下划线前缀,如

module.py
_internal_module.py

包的命名规范与模块相同。

缩写

命名应当尽量使用全拼写的单词,缩写的情况有如下两种:

  1. 常用的缩写,如 XML、ID等,在命名时也应只大写首字母,如

    class XmlParser(object):pass
    
  2. 命名中含有长单词,对某个单词进行缩写。
    这时应使用约定成俗的缩写方式,如去除元音、包含辅音的首字符等方式,例如:

    • function 缩写为 fn
    • text 缩写为 txt
    • object 缩写为 obj
    • count 缩写为 cnt
    • number 缩写为 num,等。

特定命名方式

主要是指 xxx 形式的系统保留字命名法。
项目中也可以使用这种命名,它的意义在于这种形式的变量是只读的,这种形式的类成员函数尽量不要重载。

class Base(object):
def init(self, id, parent = None):
self.id = id
self.parent = parent
def message(self, msgid):
# …略

其中 idparentmessage 都采用了系统保留字命名法。

语句

import

import 语句有以下几个原则需要遵守:

  1. import 的次序,先 import Python 内置模块,再 import 第三方模块,最后 import 自己开发的项目中的其它模块;
    这几种模块中用空行分隔开来。

  2. 一条 import 语句 import 一个模块。

  3. 当从模块中 import 多个对象且超过一行时,使用如下断行法(此语法 py2.5 以上版本才支持):

    from module import (obj1, obj2, obj3, obj4,
                        obj5, obj6)
                
    
  4. 不要使用 from module import *,除非是 import 常量定义模块或其它你确保不会出现命名空间冲突的模块。

赋值

对于赋值语言,主要是不要做无谓的对齐,如:

a   = 1     # 这是一个行注释
variable  = 2     # 另一个行注释
fn   = callback_function  # 还是行注释

没有必要做这种对齐,原因有两点:

  • 一是这种对齐会打乱编程时的注意力,大脑要同时处理两件事(编程和对齐);
  • 二是以后阅读和维护都很困难,因为人眼的横向视野很窄,把三个字段看成一行很困难,而且维护时要增加一个更长的变量名也会破坏对齐。

直接这样写为佳:

a = 1 # 这是一个行注释
variable = 2 # 另一个行注释
fn = callback_function # 还是行注释

分枝和循环

对于分枝和循环,有如下几点需要注意的:

  1. 不要写成一行,
    如:
    if !flg: pass 和 for i in xrange(10): print i 都不是好代码,

    应写成

    if !flg:
        pass
    for i in xrange(10):
        print i
    

:本文档中出现写成一行的例子是因为排版的原因,不得作为编码中不断行的依据。

  1. 条件表达式的编写应该足够 pythonic,
    如以下形式的条件表达式是拙劣的:

    if len(alist) != 0: do_something()
    if alist != []: do_something()
    if s != “”: do_something()
    if var != None: do_something()
    if var != False: do_something()
    

    上面的语句应该写成:

    if seq: do_somethin() # 注意,这里命名也更改了
    if var: do_something()
    
  2. 用得着的时候多使用循环语句的 else 分句,以简化代码。

已有代码

对于项目中已有的代码,可能因为历史遗留原因不符合本规范,应当看作可以容忍的特例,允许存在;
但不应在新的代码中延续旧的风格。

对于第三方模块,可能不符合本规范,也应看作可以容忍的特例,允许存在;
但不应在新的代码中使用第三方模块的风格。

tab 与空格混用的缩进是不可容忍的,在运行项目时应使用 –t–tt 选项排查这种可能性存在。
出现混用的情况时,如果是公司开发的基础类库代码,应当通知类库维护人员修改;
第三方模块则可以通过提交 patch 等方式敦促开发者修正问题。

已有风格

开发人员往往在加入项目之前已经形成自有的编码风格,加入项目后应以本规范为准编写代码。
特别是匈牙利命名法,因为带有类型信息,并不适合 Python 编程,不应在 Python 项目中应用。

Laravel学习笔记

文档

  1. 极客学院出品的文档
  2. Laravel中文站出品的文档

前期准备

Homestead 配置

  1. 安装VirtualBox
  2. 安装Vagrant
  3. 安装 Homestead Vagrant Box
    1. vagrant box add laravel/homestead,因各种原因有时下载会中断,所以提前自己下载下来,执行完命令后可以看到下载链接
    2. 将离线下载的虚拟机文件添加到vagrant box里 vagrant box add laravel/homestead ./virtualbox.box
  4. 配置Laravel/Homestead
    1. cd ~
    2. git clone https://github.com/laravel/homestead.git Homestead
    3. bash init 执行后会创建 ~/.homestead目录
  5. 配置Homestead
    1. vi ~/.homestead/Homestead.yaml
    2. 修改provider:virtualbox
    3. 修改folders: -map: xxx/xxx/xx 为项目路径
    4. 修改sites: -to: /home/vagrant/Code/Public
  6. 操作Homestead
    1. cd ~/Homestead
    2. 启动vagrant up
    3. 关闭vagrant halt
    4. 访问SSH vagrant ssh
    5. 连接数据库
      1. 地址 127.0.0.1
      2. 用户名homestead
      3. 密码secret
    6. 如果出现错误提示,可以用vagrant provision就一命试试看

准备工作

  1. 准备VPN翻出围墙
  2. 需要先安装Composer curl -sS https://getcomposer.org/installer | php

通过Composer安装Laravel

composer global require "laravel/installer=~1.1"

全局使用composer

sudo mv composer.phar /usr/local/bin/composer

- 阅读剩余部分 -

一些有趣的注释

/**
 *        ┏┓   ┏┓+ +
 *       ┏┛┻━━━┛┻┓ + +
 *       ┃       ┃  
 *       ┃   ━   ┃ ++ + + +
 *       ████━████ ┃+
 *       ┃       ┃ +
 *       ┃   ┻   ┃
 *       ┃       ┃ + +
 *       ┗━┓   ┏━┛
 *         ┃   ┃           
 *         ┃   ┃ + + + +
 *         ┃   ┃    Code is far away from bug with the animal protecting       
 *         ┃   ┃ +     神兽保佑,代码无bug  
 *         ┃   ┃
 *         ┃   ┃  +         
 *         ┃    ┗━━━┓ + +
 *         ┃        ┣┓
 *         ┃        ┏┛
 *         ┗┓┓┏━┳┓┏┛ + + + +
 *          ┃┫┫ ┃┫┫
 *          ┗┻┛ ┗┻┛+ + + +
 */

- 阅读剩余部分 -

我的MAC OSX系统必备软件

  1. 窗口管理 Moon
    要多强大有多强大,可以设定快捷键来调整窗口的大小,比如 半边屏幕大小、全屏、自定义大小、窗口停靠自动设置大小等等,我的配置如下图:

  2. homebrew

  3. zzh

    1. git
    2. oh-my-zsh
    3. autojump

python学习笔记

语法

输入 name = input('请输入您的姓名')
输出 print('hello')
不换行输出 print('hello',end='')
格式化输出 print('Hi %s , you have %s.' % ('Jay',10000))
常见占位符

  1. %d 整数
  2. %f 浮点数
  3. %s 字符串
  4. %x 十六进制数

类型转换 int(age) float(age)

获取字符的整数编码 ord('哈')
将整数转成字符chr(123)

生成整数序列 list(range(5)) #[0, 1, 2, 3, 4]

List:有序的集合,可以随时添加或删除元素

  1. 定义names = ['Nicolas','Jay']
  2. 使用索引访问元素值 names[0]
  3. 追加新元素到末尾 names.append('Jasmin')
  4. 插入新元素到指定位置 names.insert(1,'Jack')
  5. 删除最后一个元素 names.pop()
  6. 删除指定位置的元素 names.pop(1)
  7. 修改/替换指定元素的值 names[1]='Erika'

Tuple:叫做元祖的有序列表,相当于不可修改的List

  1. 定义names = ('Nicolas','Jay','Jack')
  2. 访问如List

dict:使用键值对存储的值,相当于其他语言的map类型

  1. 定义 students = {'Jay':'male','Erika':'female','Jack':'die'}
  2. 增加/修改/重新赋值 students[Jay] = 30 #如果key存在,这是修改key的值,如果key不存在,则是增加一个元素
  3. 访问
    1. students['Erika'] # 如果key不存在,则会报错
    2. students.get('Erika','other value') # 如果key不存在,返回None;如果key不存在并且第二个参数不为空,则返回第二个参数的值
  4. 删除 students.pop('Erika')
  5. 获取dict的所有key students.keys()
  6. 获取dict的所有value students.values()

dict与list相比,dict的访问速度更快,占用内存更大

set:没有重复元素的无序的key的合集

  1. 定义 gender = set(['male','female'])
  2. 增加 gender.add(key)
  3. 删除 gender.remove(key)

条件判断

if a>b:
    print('a>b')
    print('b<a')
elif a=b:
    print('a=b')
    print('b=a')
else:
    print('a<b')
    print('b>a')

循环
for...in

names = ['Nicolas','Jay','Jack']
for name in names:
    print(name)

while

sum = 0
n = 99
while n > 100:
    n = n + 1
    print(n)

函数

定义函数

def diy_sum(a,b):
    return a+b

# 如果要定义一个空的函数,则函数体使用 `pass` 代替即可
# 函数可返回多个值
# 返回多个值只需要写  return a,b,c 即可
# 接收返回值时可以使用 a,b,c = my_fun()
# 如果没有设置retun返回值,则自动返回None

函数的参数
所有参数都可以使用func(*args,**kw)的方式调用,args是list或者tuple,kw是dict
位置参数:为必须传入的参数,定义方式为def diy_sum(a,b) # a,b都是位置参数
默认参数:若不传入,则使用默认的值,定义方式为

def diy_sum(a,b=2,c=3):
    print('a:%s,b:%s,c:%s' % (a,b,c))

diy_sum(1) # 结果为a:1,b:2,c:3
diy_sum(1,c=4) # 结果为 a:1,b:2,c:4, b就是默认参数,默认值为2`

可变参数:允许传入任意个参数,内部会将传入的参数组合位tuple,定义方式为在参数前面增加*

# names可以是直接传入list或者tuple
def diy(*names):
    for name in names:
        print(name)

diy(1,2,3,4) # 输出结果为 1 2 3 4

关键词参数:允许传入任意个参数名,内部将会组合成dict,定义方式为在参数前面增加**

# kw参数可以是直接传入dict
def diy(a,b,**kw):
    print(a,b,kw)

diy(1,2,c=3,d=4) # 输出结果为 1,2,{'a':3,'b':4}

命名关键字参数:设置关键字参数可接受的参数,定义方式位:

# * 不是一个参数,是命名关键字的分隔符,命名关键字为必须传入的参数,可以设置默认值
def diy(a,b,*,c,d=222):
    print(a,b,c,d)

diy(1,2) # 报错
diy(1,2,3) # 报错
diy(1,2,c=3) # 输出结果为 1,2,3

导入函数

from file_name import diy_sum

高级特性

切片:对于list,tuple,dict,set,str等便捷的取值方式,使用方式S[start:end] 不包含end;
注:起始索引是0,倒数索引是-1

  1. 取索引1 ~ 3的值 S[1:3]
  2. 取前三个的值 S[:3]
  3. 取最后三个的值 S[-3:]
  4. 取倒数2~倒数4的值 S[-2:-4]
  5. 取前十个值,每2个取一个 S[:10:2]
  6. 取出所有值,每2个取一个 S[::2]

迭代:

  1. 所有迭代都使用for...in
  2. 判断是否可以迭代
from collections import Iterable
isinstance('abc',Iterable) # 如果可以迭代,则返回true,反之返回false
  1. 将list转成索引-元素的方法enumerate(list)
  2. 所有数据集合是Iterable类型
  3. 生成器的generator是Iterator类型,表示可以使用next()不断获取下一个值

列表生成式:

  1. [x * x for x in range(1,10)] 表示循环1~10,每次x相乘
  2. [m + n for m in 'ABC' for n in 'XYZ']
  3. [s.lower() for s in ['A','B','C']] 将所有字符变成小写
  4. [s.lower() for s in ['A','B','C',1,2] if isinstance(s,str)] 将所有str类型的字符变成小写

生成器:不用一次性生成完毕的列表生成式,它的类型是generator

  1. 定义g = (x * x for x in range(1,10)) 生成了一个generator
  2. 访问
    1. next(g) 会一直获取下一个元素值,如果获取完毕,会抛出异常错误
    2. 通过for迭代,for会自动处理错误
  3. generator函数,将输出的地方设置为 yield即可
def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)

o = odd()
next(o) # 输出 step 1 \n 1
next(o) # 输出 step 2 \n 2
next(o) # 输出 step 3 \n 3    

定制类:先略过,日后返回来在看 TODO

# 使用枚举类型
from enum import Enum
Week = Enum('Week',('Mon','Tue','Wed','Thu','Fir','Sat','Sun'))
Week.Mon # 可以直接调用,也可以迭代 Week.__members__

高阶函数

map():map接收俩个参数,第一个是函数,第二个是Iterable,map将传入的函数一次作用到序列的每个元素,并把结果作为Iterator返回

list(map(str,[1,2,3,4,5]))
# 结果将所有元素转成了字符串,输出结果为 ['1', '2', '3', '4', '5']
# 因为map的返回类型是`Iterator`,所以需要用转换成list才能直接显示输出

reduce():reduce接收俩个参数,第一个是函数这个函数必须接收俩个参数,第二个是Iterablereduce把一个函数作用到序列上,将结果和序列的下一个元素累计计算

from functools import reduce
def add(x,y):
    return x + y

reduce(add,[1,2,3,4])
# 输出的值是 10,相当于 add(add(add(1,2),3),4)

filter():filtermap一样,也是接收一个函数一个序列,与map不同的是,filter将传入的函数作用于每个元素,然后根据返回的TrueFalse来决定是保留还是丢弃这个元素,返回值为Iterator

def is_odd(n):
    return n % 2 == 1

list(filter(is_odd,[1,2,3,4,5])) # 输出的值为[1, 3, 5]

sorted():sorted是一个排序函数,接收三个参数,第一个参数是序列,第二个参数是key=自定义排序条件,第三个条件是reverse=True/False表示是否反向排序

L = [('Bob',20),('Erika',10)]
def by_name(s):
    return s[0]

def by_score(s):
    return s[1]

print(sorted(L,key=by_name)) # 按照名字排序
print(sorted(L,key=by_score,reverse=True)) # 按照成绩倒序排序

返回函数:在一个函数内部再定义一个函数,并且将该函数作为返回值返回,返回的时候并没有执行,需要调用之后才会执行返回函数中不要引用任何可能会变化的变量

def count(*args):
    def sum():
        ax = 0
        for x in args:
            ax = x + ax
        return ax
    return sum  # 注意,这里不可以写成 return sum(),否则会直接执行,这样返回的并不是函数本身

c = count(1,2,3) # 在这里的时候,并没有执行计算结果

print(c()) # 需要调用之后才会返回计算结果

匿名函数:使用lambda关键字表示,匿名函数只能有一个表达式,可以将匿名函数复制给一个变量,也可以作为返回值返回

lambda x : x * x # 相当于f(x),冒号前面的x表示函数参数

def f(x):
    return x * x

ff = lambda x : x * x # 将匿名函数赋值给ff

def fff(x,y):
    return lambda :x * y # 将匿名函数返回,相当于 返回函数

装饰器:可以在代码运行期间动态增加功能的方式叫做装饰器(decorator)

import functools
def log(text):
    def decorator(func):
        @functools.warps(func) # 增加这个装饰器可以使函数名称不会改变
        def wrapper(*args,**kw):
            print('%s %s()' % (text,func.__name__))
            return func(*args,**kw)
        return wrapper
    return decorator

@log('开始执行:')
def now():
    print('2016-01-14')

now() # 输出结果第一行为:开始执行:now ,第二行为 2016-01-14
now.__name__ # 结果为 wrapper,如果希望函数名称不要改变,则可以在  def wrapper(*agrs,**kw)上面增加装饰器  @functools.warps(func)即可,需要先导入functools,import functools

偏函数:偏函数(Partial function),当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。可以简单理解为其他语言里的重载,简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

def f(x,y):
    return x * y

f2 = functools.partial(f,y=3)

f2(2) # 返回结果是 2 * 3 = 6

模块(Module)

一个.py文件即是一个模块,模块通过来组织,为了避免冲突,可以设置一个顶层的包(建一个文件夹),包目录下必须有一个 __init__.py的文件,可以是空文件也可以有内容,这样python才不会将这个识别为普通目录。
模块名称是 包名.py文件名,名为包名的py文件是 包名/__init__.py

文档注释:任何模块代码的第一个字符串都被视为模块的文档注释
作者名字:__author__='xxx'

类(class)

# 默认参数是object,这里可以传入 其他类作为参数
# 若传入其他类,则表示继承这个类,若传入多个值,表示为多重继承
class Person(object):

    gender = 'male' # gender变量为Person的类属性

    # 绑定初始参数,init方法第一个参数永远是self变量,表示自身
    # 有了 __init__ 方法之后,创建实例的时候就不可以传入空的参数了
    def __init__(self,name,age):
        self.__name = name # 俩个下划线开头的变量为私有变量,无法在外部访问,但是可以使用 _Person__name 来访问
        self.age = age # 这个是正常的变量,可以在外部直接访问

    def sayHi(self):
        print("大家好,我叫%s,我今年%s岁了" % (self.__name,self.age))

wg = Person('王刚',18)
print(wg.__name) # 报错,无法在外部访问私有变量
print(wg.age) # 18
print(wg.gender) # male
wg.sayHi() # 调用sayHI方法,输出 大家好,我叫王刚,今年18岁了

class Person(object):
    # 创建类的时候,不创建__init__方法也可以
    def sayHi(self):
        print(self.name)


xshwy = Person()
xshwy.name = '王刚'
xshwy.sayHi()

wg = Person()

# 获取对象信息
type(wg) # <class 'classTest.Person'>

# 通过与types常量对比,来获取类型
import types
types.FunctionType
types.BuiltinFunctionType
types.LambdaType
types.GeneratorType

# 通过isinstance来判断
isinstance(wg,Person) # True

# 通过dir() 来获取对象信息
print(dir(wg))

# 通过hasattr() getattr() setattr()来操作对象
hasattr(wg,'age') # True
hasattr(wg,'address') # False

getattr(wg,'age') # 18
hi = getattr(wg,'sayHi') # 将wg的sayHi函数赋值给hi变量
hi() # 调用hi变量相当于调用 wg.sayHi
getattr(wg,'address',404) # 第三个参数为 无法获取参数 时报错的默认值,若不设置默认值,则会抛出错误

setattr(wg,'age',15) # 将年龄修改为15岁

面向对象高级编程

__slots__ = ('__name','age','cry') # 限制当前类能添加的属性和方法,对继承的子类不起作用

def cry(self):
    pritn('嘤嘤嘤')

from types import MethodType
# 动态的给变量增加函数,只针对当前实例,并不能作用于所有实例
wg.cry = MethodType(cry,wg)

# 若要针对所有实例,则可以给class绑定方法
classTest.Person = MethodType(cry,classTest.Person)

wg.cry() # 输出 嘤嘤嘤

#!/usr/bin/env python3
# _*_ coding:utf-8 _*_

__author__ = "CodeMart.io"

class Screen(object):

    # 使用 @property 装饰器来设置属性的 get 与 set 函数
    @property
    def width(self): # 获取width的值
        return self._width # 这里有下划线是,如果不使用下划线的话 self.width是调用的函数,而不是变量

    @width.setter # 设置width的值
    def width(self,value):
        self._width = value

    @property
    def height(self):
        return self._height

    @height.setter
    def height(self,value):
        self._height = value

    @property
    def resolution(self): # 对于resolution属性只设置了get方法,没设置set方法,这样只能访问,无法设置
        return self._height * self._width

s = Screen()
s.width = 1024
s.height = 768
s.resolution = 100 # 无法设置,抛出异常

print(s.width,'*',s.height,'=',s.resolution)

错误、调试和测试

import logging

class ErrorTest(object):
    def tryTest(self):
        try:
            r = 10 / 0
            print('result:',r)
        except Exception as e: # 捕获错误
             logging.exception(e)  # 记录错误
        finally:
            print('finally')

if __name__=='__main__':
    err = ErrorTest()
    err.tryTest()

调试

# 如果n=0,则抛出异常 'n is zero!'
# 启动Python解释器时可以用-O参数来关闭assert
assert n != 0, 'n is zero!' # 断言

# logging不会抛出异常,而是输出自定义的错误信息
import logging
# 若需要输出info级别的信息,需要在引入之后,添加下面这行配置
logging.basicConfig(level=logging.INFO)
logging.info('n = %d' % n)

测试

# 单元测试
import unittest
from errorTest import MyCalc

class TestMyCalc(unittest.TestCase):

    def setUp(self):
        print('start...')

    def tearDown(self):
        print('end...')

    def test_mySum(self):
        m = MyCalc()
        result = m.mySum(1,2)
        self.assertEqual(result,3) # 如果结果不等于3,则会报错

    if __name__ == '__main__':
        unittest.main()

# 文档测试
def mySum(x,y):
    '''
    >>> mySum(1,2)
    3
    '''
    return x + y

if __name__ == '__main__':
    import doctest
    doctest.testmod()

其他

直接运行.py文件

  1. 再.py文件开头加入 #!/usr/bin/env python3 这个要写本机的python目录
  2. 给文件执行权限chmod a+x ./file.py
  3. 执行.py文件 ./file.py

设置文件编码 # _*_ coding: utf-8 _*_

学习地址 Python基础教程

记录日常用到的LINUX命令与工具

查看目录大小 du -sh Runtime/ 结果:360M Runtime/

查看已安装的shell cat /etc/shells
切换shell chsh -s /bin/bash
创建软连接 ln -s source_file target_file

Mac连接充电提示音
开启:defaults write com.apple.PowerChime ChimeOnAllHardware -bool true; open /System/Library/CoreServices/PowerChime.app
关闭:defaults write com.apple.PowerChime ChimeOnAllHardware -bool false; killall PowerChime

pip相关

导出依赖 pip freeze > requirements.txt
安装依赖 pip install -r requirements.txt

git

提交超时The remote end hung up unexpectedly

配置git的最低速度和最低速度时间:
git config --global http.lowSpeedLimit 0
git config --global http.lowSpeedTime 999999         单位 秒
--global配置对当前用户生效,如果需要对所有用户生效,则用--system
官方文档截图

Python版本管理工具pyenv

安装 brew install pyenv
查看已安装的Python版本 pyenv versions星号表示当前激活的Python版本
只查看当前激活的Python版本 pyenv version
查看可安装的Python版本 pyenv install --list
安装新的Python pyenv install 3.4.3
卸载Python版本 pyenv uninstall
设置全局的Python版本 pyenv golbal 3.4.3
设置本地的Python版本 pyenv local 3.4.3 本地版本的优先级高于全局版本
设置面向shell的Python版本 pyenv shell 3.4.3 shell版本的优先级高于本地版本
如果无法切换python,在shell理执行if which pyenv > /dev/null; then eval "$(pyenv init -)"; fi
配置pyenv
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ exec $SHELL

sphinx的安装与使用

安装 sudo easy_install sphinx
安装主题 pip install sphinx_rtd_theme
初始化项目 sphinx-quickstart
更换主题 修改conf.py文件html_theme = '主题名称'

ffmpeg的使用

下载m3u8录像且转码为mp4 ffmpeg -i m3u8地址 -acodec copy -vcodec copy -f mp4 output.mp4
快速转码 ffmpeg -i input.flv -c copy out.mp4
从10秒开始截取60秒视频 ffmpeg -ss 10 -i input.mp4 -t 60 -c copy out.mp4

记录日常用到的SQL代码

自定义排序

SELECT * FROM `SB_SCHEDULE`
WHERE RATE IS NOT NULL AND RATE!='' 
ORDER BY SCHEDULE_DATE , FIELD(START_TIME,'8:00','18:30','21:00','21:30')

合并字段查询

SELECT CONCAT(field_a,'AAA',field_b) FROM SB_TASK  //field_a_valueAAAfield_b_value

查询结果补0

SELECT LPAD('AAA',6,0) // 000AAA
SELECT RPAD('AAA',6,0) // AAA000

查询结果包含

SELECT * FROM STUDENTS WHERE ID IN(1,2,3)

查询结果排除

SELECT * FROM STUDENTS WHERE NOT IN (1,2,3)

记录日常用到的JS代码

控制台调试输出 console.log();

获取radio被选中的值$("input[name='rate-control']:checked").val()

判断checkbox是否被选中$("#annoy").is(':checked')

修改元素的css样式$('#progress_bar').css("width", "100%");

隐藏、显示元素$('#process').hide(); $('#process').show();

获取JS方法的参数 arguments[0]

刷新当前页面 location.reload()

定时器 间隔指定的毫秒数不停地执行指定的代码 setInterval("alert(123)",1000)

间隔指定的毫秒数不停地执行指定的代码 setTimeout("alert(123)",1000)

AJAX同步设置

$.ajaxSetup({
    async: false
});

AJAS POST提交

$.post(getStudentInfoUrl, {
    student_id: student_id, 
    teacher_id: teacher_id
}, function (data, textStatus) {
    students = data;
});

转换JSON $.parseJSON(students);

循环

$.each(students, function (i, val) {
    console.log(val);
});