|
| 1 | +Python 学习笔记 |
| 2 | +====== |
| 3 | + |
| 4 | +### 类型 |
| 5 | +python 有四种类型,分别时整数,长整数,浮点数和复数 |
| 6 | + |
| 7 | +1. 整数,普通的使用方法,如2, 56,65535等等 |
| 8 | +2. 长整数,就是表示范围更大的整数 |
| 9 | +3. 浮点数,3.23, 3.4E-4表示的时3.4乘以10的-4次方 |
| 10 | +4. 复数,(-5+4j) |
| 11 | + |
| 12 | +### 字符串 |
| 13 | + |
| 14 | +*自然字符串*:前面加上r或者R来表示的,如r"This is a test\n"。这样,就会照它原来的样子翻译,而不会使用转义字符翻译字符串了。(使用正则表达式的话需要使用自然字符串) |
| 15 | + |
| 16 | +*Unicode字符串*: 使用Unicode编码字符串(特别时对于不仅仅包含英文的字符串) |
| 17 | + |
| 18 | +连接字符串:当两个字符串直接相邻时会自动连接起来。比如,'what\'s this ''is a bug',这两个字符串会被自动连接为'what\'s this is a bug' |
| 19 | + |
| 20 | + |
| 21 | +*转义符*: 单引号使用一个'\\'来转义,双引号使用两个`\\`来转义显示。行末加上`\`可以连接字符串,而不是换行。 |
| 22 | + |
| 23 | +*字符串是不可变的* |
| 24 | + |
| 25 | +*单引号和双引号是表达的意义是一样的* |
| 26 | + |
| 27 | + |
| 28 | +### 引号 |
| 29 | + |
| 30 | ++ 单引号:指示一个字符串 |
| 31 | ++ 双引号:指示一个字符串(与单引号相同,里面可以包含单引号,直接输出而非转义) |
| 32 | ++ 三引号:指示多个字符串,可以包括多行 |
| 33 | + |
| 34 | +> 单引号的例子: |
| 35 | + 'what is this', 'what\'s this' (里面使用了转义字符) |
| 36 | + |
| 37 | +> 双引号的例子 |
| 38 | + “what is this”, "what's this"(对于里面的单引号不需要使用转义字符,直接输出) |
| 39 | + |
| 40 | +> 三引号的例子 |
| 41 | + \'''This is the first line |
| 42 | + sencond line |
| 43 | + third line''' |
| 44 | + |
| 45 | +### 基本的数据类型是数和字符串,后面的类型为类 |
| 46 | + |
| 47 | +### 关于运行方式的一些说明: |
| 48 | +Python的运行方式,和其他程序脚本语言的方式是一样的,运行程序,脚本都是可执行的程序,因为是解释型语言。可以直接用python xxx.py的方式运行,指定了解释器就是python,也可以在脚本的头部加入 #!/usr/bin/python 的方式来指定解释运行的脚本,然后赋予可执行的权限,chmod +x xx.py,这样在Linux下面就可以使用./xx.py的方式来直接运行这个脚本。 |
| 49 | + |
| 50 | +### Python的类型 |
| 51 | +对于C/C++语言的程序员而言,python是没有类型的,不需要声明类型,直接使用变量就可以了。另外,字符串是无法修改的,只能修改的是变量。 |
| 52 | + |
| 53 | +### Python的物理行和逻辑行 |
| 54 | ++ 物理行:就是*程序员*的眼光看到的一行。实际上就是物理上看到的一行一行的概念。 |
| 55 | ++ 逻辑行:就是*Python*程序解释语言时认为的一行 |
| 56 | + |
| 57 | +一些例子说明物理行和逻辑行的关系: |
| 58 | + |
| 59 | +1. i = 5; print i(一个物理行对应多个逻辑行) |
| 60 | + |
| 61 | + 从字面上可以看到只占用了一行,因此物理行就是一行,而这个语句包含一个分号,因此被python认为是两个语句(*强烈建议不要使用分号,大部分python程序中都没有分号,而且最好一个物理行对应一个逻辑行*) |
| 62 | + |
| 63 | +2. s = ''' This is the first line \ |
| 64 | + |
| 65 | + This is the second line'''(一个逻辑行对应多个物理行) |
| 66 | + |
| 67 | + 这就是签名所说到的以\来连接字符串的,从物理行角度看有多行,而python则认为他们是一行,因此就有这种关系。(*明确的行连接*,不明确的使用圆括号,方括号等,后续继续学习) |
| 68 | + |
| 69 | +### 缩进 |
| 70 | +Python中的缩进非常重要,同一个块中的缩进必须相同,否则*不能运行*。 |
| 71 | +保持良好的编程风格,使用统一的缩进,不要混合使用空格和制表符。 |
| 72 | + |
| 73 | +## 运算符和表达式 |
| 74 | +大部分运算符和C/C++,Java中的类似,但是Python有几个特殊的需要注意一下: |
| 75 | + |
| 76 | ++ 幂运算符(`**`),比如`3 ** 4` = 81 |
| 77 | ++ 取整数运算符(`//`),比如 5 // 4 = 1(整数部分) |
| 78 | ++ 逻辑运算符(and, or, not),这些运算符不同于&&, ||, !这些C/C++的运算符,注意一下。 |
| 79 | + |
| 80 | +## 控制流笔记待补充 |
| 81 | + |
| 82 | +## 控制流 |
| 83 | +*break*: 特别注意,如果从for或者while循环中终止的话,则对应的else从句永远都不会执行。(break终止的情况) |
| 84 | +*continue*:忽略后面执行语句,继续执行循环(与break不同,break会退出循环) |
| 85 | + |
| 86 | +### 函数 |
| 87 | +可以给一个块定义一个函数,该函数能够在程序任何地方多次调用。 |
| 88 | +*函数的定义方法:* |
| 89 | +使用def关键字,并且后面接上函数名称,然后括号,括号中可以使用变量名,最后接上冒号即可。注意一个函数就是一个块,所以要注意缩进。 |
| 90 | + |
| 91 | +函数可以给定参数,传递的参数位实参,而函数原型中定义的参数为形参。 |
| 92 | + |
| 93 | +### 局部变量和全局变量 |
| 94 | +函数内定义的变量为局部变量,对于局部变量的修改仅限于函数内部,无法影响到外面。如果内部想使用外面的变量,使用global标识符来标记这个变量是外部定义的,这样,我们再对这个变量进行修改的时候,就是修改的外部变量,就可以在函数体内部修改外部变量,影响外面的值。 |
| 95 | + |
| 96 | +### 默认参数值 |
| 97 | +使用等于号为默认参数指定值,这样用户可以不指定该参数,默认使用该参数,即原型中有两个参数,我可以只指定一个,第二个使用默认的参数(这样要原型定义了默认参数) |
| 98 | +*注意*:默认参数的默认值必须是定值,不可变的。另外,和C++一样,默认的参数值必须放在右边,不能先是默认参数,后是必须参数。 |
| 99 | + |
| 100 | +### 关键参数 |
| 101 | +通过函数名来指定值,以前的C/C++等语言和python的前面哪些方式,都是通过位置,按照先后顺序依次赋值的,参数传递就只有这种方式。 |
| 102 | +而这里python可以通过指定变量名来指定参数,如果不是变量的,则使用位置变量,即按照定义的位置顺序来赋值操作。 |
| 103 | + |
| 104 | +### 返回值 |
| 105 | +如果没有返回值的话,python默认返回None,即空 |
| 106 | +如果函数体不定义的话,相当于一个Pass语句(空语句) |
| 107 | + |
| 108 | +### DocStrings |
| 109 | +可以在类,模板,函数中增加文档字符串信息,以函数为例,在函数的第一行,用三引号描述该函数功能,然后空行,接下来一行再详细描述,并结束字符串。 |
| 110 | +最后,可以使用function.__doc__的方式来输出这些文档字符串信息 |
| 111 | +该信息可以用来自动生成说明文档,或者帮助文档等 |
| 112 | + |
| 113 | +## 模块 |
| 114 | +使用import xxx来引用某个模块,如果要使用模块的成员,用点号运算符,如sys.argv表示的就是输入参数的列表信息,注意的是该列表的第一个参数是脚本的名称,后面才是列表内容。 |
| 115 | +可以使用模块中的变量信息,而且不必要担心名称重复,因为签名sys的模块名已经定义了模块。另外,关于模块放置的路径,在当前文件夹是可以的,否则就要放在system的path下面,否则是找不到的。 |
| 116 | + |
| 117 | +模块的文件名必须以py结束,模块的目的就是为了复用。(函数当然也是可以的,不过要实现更为庞大的复用则需要用到模块) |
| 118 | + |
| 119 | +### pyc文件 |
| 120 | +二进制文件,起到隐藏源码的作用,而且与平台无关,需要注意的是,不同版本的python编译出来的pyc文件是不同的,不能通用。 |
| 121 | + |
| 122 | +如果要避免输入sys的话,可以使用from sys import argv,这样以后使用argv的话就是用的sys中,不过这个不是好的做法,因为可能有名称冲突,而且不易读(使用sys.argv更易读) |
| 123 | + |
| 124 | +### 模块名称 |
| 125 | +模块名称使用__name__来标记,使用场景: |
| 126 | +有些代码只想在主块中执行时才使用,而作为其他模块的子模块(输入,也就是说其他模块调用这个模块的时候)时不想执行,可以使用到该变量来标记: |
| 127 | + |
| 128 | + if __name__ == '__main__': |
| 129 | + xxxxx ### 作为主块的时候执行 |
| 130 | + else: |
| 131 | + yyyyy ### 只在子模块的时候执行 |
| 132 | + |
| 133 | +这样,比如为test.py文件,那么直接运行./test.py的时候,执行的为main,此时执行xxxxx,而如果是利用import test的方式,执行(命令行中,python, import test)的话,则作为子模块执行,此时执行的是yyyyy。 |
| 134 | + |
| 135 | +### dir() |
| 136 | +dir不提供参数,则会列出当前模块定义的列表,如果给定参数,即模块名,则会列出该模块定义的名称列表。 |
| 137 | +可以使用del删除一个参数,就像从来没有存在过一样。 |
| 138 | +dir()会列出所有名称列表,而del会删除对应的名称列表,此时再用dir()会发现不再存在。 |
| 139 | + |
| 140 | +## 数据结构 |
| 141 | +Python有三种数据结构,列表,元祖和字典 |
| 142 | + |
| 143 | +### 列表 |
| 144 | +列表以方括号来表示,是一个类(就像int也是一个类一样,可以访问列表的函数,比如mylist.append函数就是向列表的末尾添加元素一样),每一个项目通过逗号分开 |
| 145 | +下面就是一个列表的例子: |
| 146 | + |
| 147 | +['test', 'a', 'bbbb'] |
| 148 | +需要注意的是,list是可变的,而字符串是不可变的,因此对list的修改,比如增加,删除,添加等,都会改变原有list的状态(具体关于list的函数可以参照help文档) |
| 149 | + |
| 150 | +### 元祖(tuple) |
| 151 | +元祖是*不可变*的,因此不能修改它的值。元祖使用的是圆括号和逗号分开, |
| 152 | +元祖可以直接叠加,比如: |
| 153 | + |
| 154 | + zoo = ('monkey', 'tiger', 'snake') |
| 155 | + new_zoo = ('elephane', 'dolphine', zoo) |
| 156 | +那么就可以直接用zoo构建一个新的对象new_zoo,而且可以通过下标访问元素,比如,zoo[2], new_zoo[0], new_zoo[2][2]等等,注意下标起始为0,而不是1. |
| 157 | + |
| 158 | +#### Tips #### |
| 159 | +1. 列表之中的列表不会失去它的身份,即列表不会像Perl中那样被打散。同样元组中的元组,或列表中的元组,或元组中的列表等等都是如此。只要是Python,它们就只是使用另一个对象存储的对象。 |
| 160 | + |
| 161 | +2. 一个空的元组由一对空的圆括号组成,你必须在第一个(唯一一个)项目后跟一个逗号,这样Python才能区分元组和表达式中一个带圆括号的对象。即如果你想要的是一个包含项目2的元组的时候,你应该指明singleton = (2 , ) |
| 162 | + |
| 163 | +3. 元组和打印语句(使用%s, %d来打印对应的输出结果) |
| 164 | +如: |
| 165 | + |
| 166 | + 'Her name is %d, age is %d' %(name, age) ## 分别对应替换位对应的值 |
| 167 | + |
| 168 | +注意和C/C++不同的是,这里没有逗号分割开来,直接是字符串加上%来进行转换 |
| 169 | + |
| 170 | +### 字典 |
| 171 | +表示方法:使用花括号包围,并用冒号表示一个个键值对,然后以逗号分割开来。 |
| 172 | +如:{key1:value1, key2:value2}, |
| 173 | + |
| 174 | +#### Tips |
| 175 | +键是唯一的,不可变的,而且最好简单,值则可以是可变的或者不可变的。 |
| 176 | + |
| 177 | + |
| 178 | +### 序列 |
| 179 | +列表,元组和字符串都是序列,序列支持的是index操作和slice操作,即index可以直接通过下标来访问元素,而slice则可以通过切片访问一部分元素。 |
| 180 | +python的下标从0开始,可以为负数,-1表示最后一个元素 |
| 181 | +*Note*:注意的是,切片的时候提供两个下标,比如[1:5]表示的从[1,5),即这个范围表示的从起始位置开始(含起始位置),不包括最后一个下标,即只能表示1,2,3,4这四个元素的索引。 |
| 182 | + |
| 183 | +### 参考Reference |
| 184 | +当对一个变量赋值,用对象传值的时候,注意变量自己不是一个新的对象,而只是只想原来的对象而已。 |
| 185 | +如: |
| 186 | + |
| 187 | + list = ['a', 'b', 'c'] |
| 188 | + mylist = list |
| 189 | + del list[0] |
| 190 | + print list |
| 191 | + print mylist ###注意的是list和mylist都是指向相同对象,因此都没有第一个元素 |
| 192 | + |
| 193 | +而如果似乎拷贝的话则不同,如 mylist = list[1:3],此时会创建新的对象 |
| 194 | + |
| 195 | +### 字符串的内容str |
| 196 | +关于具体的内容可以参考help文档中关于str的描述。 |
| 197 | +几个常见的用到哦啊的函数: |
| 198 | +startswith(): 以……开始 |
| 199 | +contains():包含…… |
| 200 | +find():查找是否有某个子字符串 |
| 201 | + |
| 202 | +### 附:正确使用帮助 |
| 203 | +可以在命令行中进入python后,输入help('xxx')来查询关于xxx的文档,注意,一定要加上引号,否则会提示错误。 |
| 204 | +也可以输入help(),进入到help>模式,此时直接输入xxx,就可以查询到相关信息。 |
| 205 | + |
| 206 | +### 解决问题(一个实际的小项目) |
| 207 | +项目简介:做一个备份系统,能够将某些目录下面的文件备份到某个指定目录下面,并以zip包的形式打包,文件名为备份时候的时间。 |
| 208 | +知识点总结: |
| 209 | +1. 需要使用到的库包括,time,os,其中time库用来获取备份时候的时间,使用 |
| 210 | + |
| 211 | + filename = time.strftime("%Y%m%d%H%M%S") + '.zip' |
| 212 | +来保存获取算时间,特别注意的是这里括号中的字符大小写一定要弄清楚,否则会出现显示的时间不对(具体的format可能还需要再研究一下) |
| 213 | + |
| 214 | +2. 执行某些系统命令,需要使用os库中的system方法实现,比如这里zip打包命令: |
| 215 | + |
| 216 | + os.system(command) |
| 217 | + |
| 218 | + 这里就是执行command = zip -qr dest src |
| 219 | +的命令,只是说需要转换一下格式,比如字符串拼接,处理,格式化字符串而已。 |
| 220 | + |
| 221 | +3. 还需要一些字符串的处理,比如多个目录的连接,组合成为一个字符串,这样作为zip的第二个参数,即待压缩的路径,此时用的是: |
| 222 | + ' '.join(source) |
| 223 | +来处理,表示对于元祖source中的每个项目都用空格来链接起来。 |
| 224 | + |
| 225 | +### 软件开发流程 |
| 226 | +1. 什么(分析) |
| 227 | +2. 如何(设计) |
| 228 | +3. 编写(实施) |
| 229 | +4. 测试(测试与调试) |
| 230 | +5. 使用(实施或开发) |
| 231 | +6. 维护(优化) |
| 232 | + |
| 233 | +从上面这个小程序可以看到,Python的功能很强大,可以完成这些工作,而且代码量很小。特别是,从改进的V1到V4版本,每一个都是在原有的旧的 |
| 234 | +基础上完成的,因此可以看到,软件的开发,前期需要分析,从简单入手,完成某些特性后,使用,调试Bug,如果发现有新的feature,则加入需求 |
| 235 | +中,并继续开发,如果有问题,则调试。测试工作也非常重要,整个过程一气呵成 |
| 236 | + |
| 237 | + |
| 238 | +## 面向对象与类 |
| 239 | +1 Python的类的函数都有一个默认的参数,不需要你赋值,该变量就是指这个类本省,通常命名为self。 |
| 240 | +2. 使用对象的类方法,直接和原来定义函数的方法类似,def定义函数即可,需要注意的是,要加上那个默认的参数self,即使函数体为空,然后再调用这个函数的时候,又不需要传递参数,同上面的说法(另外,新建一个类对象不是像C++那样new出来,直接调用类构造函数即可) |
| 241 | +3. __init__方法 |
| 242 | +相当于C/C++中的构造函数的方法,并不需要显示调用,用来完成创建对象时候的初始化工作。 |
| 243 | +4. __dele__方法 |
| 244 | +相当于析构函数,只不过不能保证它是何时执行的。 |
| 245 | +5. 类变量和对象变量 |
| 246 | +类变量是该类的对象所共有的,相当于static变量,所有的对象对它的修改都会影响到它的值。对象变量则是对象独有的,每一个对象都有这样一份拷贝。 |
| 247 | +定义类变量就是在类中直接定义,而对象变量则是通过构造函数来传递参数的形式进行赋值和初始化 |
| 248 | +6. 继承。使用元组的方式来定义继承关系,如: |
| 249 | +class myclass(superclass): |
| 250 | +这种方式来定义继承的关系,即myclass继承自superclass来实现。 |
| 251 | +注意:python不会自动调用基类的构造函数,需要自己手动指定调用。 |
| 252 | +另外,调用时还需要注意使用到self参数,保证参数的完整性 |
| 253 | + |
| 254 | + |
| 255 | + |
| 256 | + |
0 commit comments