从今天开始学习一下Python,用于替代shell,还能做一些自动化打包,git hook脚本,自动化测试等等工作;
1.Python里文件名以小写下划线来命名,如aa_bb.py;变量名也是,如name_length
2.Python里语句最后的分号可要可不要;
3.Python里print默认是会最后输出换行,即print("aa")等价于print("aa", end = ' '),如果不要换行可以print("aa", end = '')来手动指定;Python2里是通过print("sfjl"),来实现,即后面加个逗号;
4.Python里""和''双引号和单引号都是字符串,和js一样;
5.Python里转义字符也是用开头,如 等
6.Python里面变量定义不需要有var之类的前缀;如果一个变量抛了异常说没有定义,则说明要么这个变量没有赋值,要么就是拼写错误;
7.Python2里打印可以是print "sfjkl",不过Python2.7也支持print("asf")的打印方式;
8.Python里**表示两个乘方运算,即10 ** 2等于100;
9.Python里浮点数可能因为精度问题会打印不合自己需求的数值,如0.1+0.3会变成0.4000000...4这样的数;【后面有方法可以改进】
10.Python3和Python2里整数相除的区别有3/2在Python3里是1.5,而在Python2里是1(注意是直接删除了小数部分而不是四舍五入),所以为了兼容最好是都写3.0/2或3/2.0
11.Python里字符串和数值相加不会将数值默认转换为字符串,而是报错,即"aa" + 5会报错,需要用str(5)来手动转换
12.Python里的注释是#开头
13.Python里数组或列表(list)是用[]开定义的,如list = ['sss', 'bb'],打印也是输出这个样子(注意如果是"sss"输出数组时会被格式化为单引号),而且允许混合不同类型如list = ["aa", 4]打印['aa', 4]不会报错
14.Python的列表访问方式是list[0]来访问第一个元素;修改则是list[0] = 'aa'来覆盖第一个元素值,注意这里不同类型也可以覆盖,即list[0]原先的值可以是数值类型;
15.Python里通过list.append('ccc')来在末尾添加元素;list可以是定义为空列表,如list = [];插入指定位置的值用list.insert(0, 'aaa')就会在开头插入元素;
16.Python里删除list中的某个元素比较特殊,用del list[0]来删除;还有个pop()方法可以弹出最后的元素;pop还可以指定下标,即list.pop(0)是删除第一个元素同时返回它;而del不返回被删除的元素;
17.list还有remove方法,它可以通过值来删除,如list.remove('aa')会删除list中值是aa的元素(有多个则只删除第一个匹配元素,没有对应元素则报错)
18.list可以有二维的概念,如list = ['aa', 4, ["uu", 88]]是正确的写法;
19.如果在终端上输入python或python3(根据自己的环境),会出现>>>用来输入Python代码,注意这个是上下文环境连续的,即第一行定义的变量可以在后面的>>>里使用;
20.list可以通过list.sort()来将list里的元素进行排列(按数值或按字母),这里要求要么元素都是字符串,要么都是数值(可以整型和小数,但是不能数值和字符串共存),sort()后list本身会改变排序而不是返回一个新的列表
21.Python里boolean的值是True和False,注意开头是大写;
22.Python里函数的调用传参数时如果有多个参数可以【or必须?】写清楚参数名,如list.sort(reverse = True)会令list反序排列;(如果只有reverse一个参数应该是只需要提供值才对?)
22.list还有sorted()方法来返回一个排序后的list,但是本身的元素顺序不改变;如list.sorted()会返回一个新的排好序的列表,list本身没有发生改变;
23.list[-1]返回最后一个元素,当然也可以用list[len(list) - 1]来实现;如果list没有元素则会报错;list初始化时的元素定义还可以是变量名;
24.Python是用for item in list:的方式来遍历list的所有元素的(不知道Python里有没有对元素类型的判断?毕竟它里面可以是多种类型混合),注意for item in list:的下一行如果是属于for in作用域,那么就要求必须比for的位置前面加一个tab(或者空格也行,但是同一for作用域的多条语句前面的间隔必须一样,比如都是两个空格或者都是一个tab之类的);
24.Python里如果两个语句是同一作用域,那么它们前面的间隙必须一样,比如两条print语句,第一条前面没有空格,第二条也必须没有,否则就会报错;Python里没有花括号就靠间隔来实现作用域的分割;
25.注意Python里for item in list:在for结束后item是不会释放的,外界仍然可以使用它(它在后续里的值是最后一次迭代的list元素值),这很容易造成逻辑错误,所以要谨慎缩进的错用或漏用;
26.del除了可以删除list中的元素,它还能释放变量;如msg = "sfjl";del msg;后msg不可再引用,否则报错未定义;
27.Python里没有引用和值的说法,所以a == 'sss'是恒比较值的;
28.Python里除了for,像if else等语句后面也是需要冒号的;条件语句里有if elif else这三个关键字;
29.Python里Map其实就是JSON格式的对象,如map = {'key1': 3},注意key也可以是数值;新增pair和修改的方式一样如:map['uu'] = '8s'会往map里添加key是uu值是8s的键值对(如果key已存在则是修改);
30.删除字典里的pair也是可以用del,如del map['ss'],注意如果map的初始化的内容比较多,则可以让{和}各占一行,然后第一个元素相对上一行缩进,后续的所有元素和最后的}保持和第一个元素缩进一致;
31.input方法可以接受用户的终端输入,比如content = input('please enter your content:")会输出这段话同时等待用户输入,用户输入内容后按回车键将输入的内容存储在content变量里(input()方法参数也可以没有);
32.content = int(content)能够将数值字符串转换为数值(注意不能是小数),小数用float(content)转换;
33.Python里两个字符串也能用>和>=之类的比较符进行比较,前面的字母越小它的"值"也越小;
34.while循环的写法是while cond <= 5:然后下一行记得缩进;
35.注意变量必须有值才能参与比较,否则提示undefined(其他语言还有null的概念,即默认值是null,所以不需要初始化,但是Python里必须要初始化)
36.Python里也有break和continue,和其他语言一个意思;
37.Python里"""开头和"""结尾是文档注释,一般放在类或函数签名的定义的下一行,描述类或函数的作用;
38.函数的定义是def func():可以有参数,注意括号不能少;参数调用可以加上参数名,如def func(name):,调用的时候可以是func('sf')也可以是func(name = 'skf')
39.Python里没有函数重载的说法,哪怕是参数个数不一样;
40.Python的函数参数形参可以有默认值,如def func(name, age = 4):,那么调用的时候可以func(name = 'sf'),也可以func('sf'),不指定名字则是从第一个参数逐步匹配;注意如果指定参数名字则顺序可以乱,如func(age = 8, name = 'ss')
41.Python可以return返回一个值(或一组值),如果没有return则默认返回None(可打印,类似True之类的)
42.Python里对空字符串判断会认为是False,但是直接和False比较也是False,如if '':的else会成立,但是'' == False会返回False
43.Python里元组类似列表,不过是不可修改的,元组是('aa', 8)这样的定义,列表是['aa', 8]这样的定义(获取元素值方式一样);
44.函数可以返回任意类型的值,它的参数如果是列表,则函数里修改了列表,调用者的实参也会跟着修改,如果不希望被函数内部修改外部的实参列表,可以这样定义函数def func(list[:]):,这样调用func时实参就会深拷贝一个列表给func
45.函数可以传递任意个参数,定义方式是def func(*params):,然后调用可以是func('aa', 8, 9)这样任意个参数,这些参数在函数里面会变成名叫params的元组;
46.函数里可以不定长参数和普通参数混合,不过要求不定长参数放最后面,即def func(name, *params):
47.参数是**map表示这个是一个字典参数,它的实参是类似key1=4,key2='8s'这样的数据(Python会自动将它们组合成pair存入到map里)【但是注意如果有name, **map这样的方法,那么传参时无法做到往map里传key是name的pair,不过可以约定这种情况下前面的name可以写成name_或者name__防止出现冲突】
48.可以将函数def add(a, b):写到一个文件里,如utils.py,然后其他文件可以引用这个文件,如hello.py里可以import utils(不一定要开头import),然后用utils.add(3, 4)来调用;
49.还可以用from utils import add来导入模块(.py文件)中的部分函数,但是这种情况下不能写成utils.add(3, 8)了会报错,只能写成add(3, 8)【但是这个有疑问,如果两个模块都有add,都用这种方式导入不是会冲突吗?】
确实会冲突,但是可以用别名,即from utils import add as add01,这样调用的时候就是用add01(3, 8)就行了;也可以为模块指定别名,import utils as helper
还可以用from utils import *来导入utils的所有函数【不过与其这样还不如直接import utils更好,至少不需要考虑函数冲突,最多就是模块名冲突定义模块名别名即可】
50.注意,导入的时候如果函数名冲突是不会报错的,而是后导入的会覆盖前面的;
51.Python里类的定义是class ClassName():【Python2里是class ClassName(object):】(Python3里类名后面的()可不要),然后类里的特殊方法是__init__(self, pro1, pro2):,注意Python里所有的__和__结尾的方法都是系统特殊方法;然后创建类对象是通过ClassName(pro1, pro2)然后会自动调用__init__(self, pro1, pro2):将两个参数给初始化方法来初始化类对象的属性【属性必须初始化否则等于没有这个属性】,注意在初始化函数里self.pro1 = pro1则pro1是public的,如果是self._pro1则是protected的,如果是self.__pro1则是private的(实例方法也一样);【但经过测试没用,并不是真正的private或protected,只是大家的一种约定】
52.对于是public的属性(没有下划线开头),外部可以直接用dog1.age = 10这样的写法来修改实例的属性值;Python3里还有__call__(self, voice):这个特殊方法,它可以使得这样调用dog1('voice')就是调用__call__方法;
53.Python里除了实例方法还有静态方法和类方法,静态方法没有self参数而且上面要加上@staticmethod注解,而类方法也没有self参数但是第一个参数是cls且要加上@classmethod注解;类方法和静态方法的区别在于静态方法只能通过类名.方法名调用;而类方法则实例名或类名.方法名都可以调用;
54.Python里面类可以继承,通过class SubClass(SuperClass):来实现继承,然后在初始化方法里Python3通过super().__init__(...)来为父类的属性初始化;而Python2里通过super(SubClass, self).__init__(...)来实现;
55.Python里面重写父类方法其实就是在子类里定义一个同名方法即可;
56.Python里类的属性可以是类实例,如果要访问类实例中的类实例的属性是通过dog1.owner.name来访问(前提是public)
57.msg = r'mm kk'然后打印msg会输出mm kk而不是mm然后tab然后kk
58.Python里有异常处理,异常处理里面有四个关键字,try和except和else和finally,其中except就类似java的catch,用于匹配特定的异常,而else则是在特定异常后面加的用于匹配其他异常(包括没有异常的情况),finally则和java一样;可以用pass关键字来忽略except或else:里的处理
59.Python里if __name__ == '__main__'最大的意义其实就是告诉别人程序的入口是哪里【被导入的模块里的这个判断不会生效,只有被直接python xx.py运行的模块里的这个判断才会为真】
60.Python3通过pip3命令来安装模块【类似maven】,Python2是pip命令;
61.Python里对变量或方法的使用不是必须在声明之前先定义方法或变量,只要在调用的时候存在即可,还有就是方法里面抛异常不会影响外层的输出【和js很像】
62.Python属性定义还可以放在class的下一行(或文档注释下一行)定义及默认值设置,而不是必须在__init__方法里;
63.Python里如果某个方法不需要有实现,也可以用pass来忽略(如__init__方法里面如果不需要赋值),而不是pass只能用于异常里忽略;
64.经过测试,Python3里类方法和静态方法没有区别,并不是说静态方法就不能用实例调用,或者类方法就不能用实例调用;
65.注意在if内或者for内或者while内定义的变量如果没有del,那么外部的作用域是能够访问的(类似js的var,但是let不会)
66.Python里-1的下标代表最后一个元素(倒数第一),-2代表倒数第二个元素,以此类推。
67.Python可以通过os.system("ls|grep a")来执行系统命令(不过它不能像直接在终端上执行ls|grep a会把a字符标红);
68.Python里建议indent是4个空格。
69.Python无论是3还是2最好都在是__main__的Python文件最上面加上from __future__ import division, print_function来填平2和3之间的一些差异(本来是想搞一下版本判定,在if内不能用from xxx的写法)
70.Python里的字典(JSON对象)不能像js一样用map.prop来调用{'prop':4}这个属性值,而必须是map['prop'],而js两种都行;
71.在Python3里:字符串默认值可以是'',数组默认值是[],字典默认值是{},数值默认值是0,而复合对象默认值是None
72.Python3可以限定参数类型和返回值类型,如:def test(a:int, b:str) -> str:
73.Python3里取反用~(其他语言一般是!),不等于是!=,然后3/2是1.5,而3//2是1(但是-1//2却又是-1,因为m//n是根据m/2的结果向下取整)
74.为了尽可能的和Python2和Python3兼容,最好在每个*.py文件最上面加上:# coding:utf-8
75.Python可以通过isinstance和type内置函数来判断对象的类型:
isinstance() 和 type() 的区别在于: type()不会认为子类是一种父类类型 isinstance()会认为子类是一种父类类型 class A: pass class B(A): pass isinstance(A(), A) # returns True type(A()) == A # returns True isinstance(B(), A) # returns True type(B()) == A # returns False
76.Python没有package关键字,也没有mod这样的关键字,它就是通过目录名和文件名来对应package的名字的,而且它的模块名(包名)是有层级关系的,比如在aaa目录下有test.py,那么外部的.py文件导入test模块的时候是aaa.test;而go没有这个层级,
个人觉得Python的模块比go的好;
77.Python通过pip来安装网络依赖,命令为pip install zipfile(这里pip可能会是pip3,可以通过pip --version或pip3 --version来查看pip属于哪个版本的Python)(zipfile则是待安装的网络模块)
78.Python获取执行文件.py的文件路径可以通过获取当前工作目录加上__file__拼接实现;当前工作目录可以用os.getcwd()实现;然后路径拼接用os.path.join(p1, p2);再可以通过os.path.dirname(fp)来获取fp文件所在目录;
用os.path.splitext(file)[0]可以获得绝对/相对路径上的文件的前缀名(后缀名用[1])
79.Python3里判断不等于None不要用!= None而是用 is not None;对于True和False也是用is True这样的写法;
80.Python里@property注解可以让一个方法变成以属性的方式调用;
81.“main”里要调用全局方法,要求全局方法在“main”上面声明