Python入门基础知识
Python的历史
Guido van Rossum (吉多·范罗苏姆,人称“龟叔”,荷兰人),于1989年开始写Python语言的编译器
Python的名字来自龟叔所挚爱的电视剧Monty Python‘s Flying Circus,1991年正式诞生
Python解释器如今有多个语言实现,我们常用的Python是CPython(官方版本的C语言实现),其他还有Jython(可以运行在Java平台)、IronPython(可以运行在.NET和Mono平台)PyPy(Python实现的,支持JIT即时编译)
2008年出了Python3.0意在清理Python2中的冗余与错误设计
Python2.7.x将是Python2系列的最终版本,Python官方对其最终维护到2020年
Python3中最大的跳跃在于,全部使用unicode字符
Python3.6(含)版本之后支持使用新的字符串格式化方式 即:
name = "Jet Bi" print(f"Hello,{name}!") # 输出结果: Hello,Jet Bi!
Life is shot, you need Python. 人生苦短 我用Python!
环境搭建
- 下载安装并配置镜像源
- 清华大学Anaconda镜像源:https://mirror.tuna.tsinghua.edu.cn/help/anaconda/
- 注意添加
Path
环境变量,安装时直接勾选Add Minicoda3 to the system PATH environment variable
即可,手动添加的话就是如下4个- D:\Miniconda3;
- D:\Miniconda3\Library\mingw-w64\bin;
- D:\Miniconda3\Library\usr\bin;
- D:\Miniconda3\Library\bin;D:\Miniconda3\Scripts;
- conda 常用命令
- 查看环境
conda env list
- 创建环境
conda create -n demo python=3.8.3 # demo为自定义的环境名称
- 进入环境
conda activate demo
- 退出环境
conda deactivate
- 删除环境
conda evn remove -n demo
- 安装包
conda install jupyter # jupyter为要安装的包的名称
- 更新包
conda update jupyter
- 卸载包
conda uninstall jupyter
- 克隆环境
conda create -n demo_copy --clone demo
- 清理索引缓存
conda clean -i
- 查看环境
- 使用
conda env list
出现重名环境,又删除不掉时,可以找到.conda/environments.txt
文件,删除其中内容即可 - jupyter 常用命令
- 运行jupyter
jupyter notebook
- 生成配置文件
jupyter notebook --generate-config
- 更改默认目录,在配置文件
jupyter_notebook_config.py
中更改c.NotebookApp.notebook_dir
项的值 - 查看帮助
jupyter notebook --help
- 运行jupyter
Python编码规范
命名要通俗易懂,不要单独的使用Python关键字和保留字
包名: 使用小写字母、数字、下划线的组合,且不以数字下划线开头 如:
package_name
模块名: 使用小写字母、数字、下划线的组合,且不以数字下划线开头 如:
module_name.py
类名: 采用帕斯卡命名法,首字母大写 如:
ClassName
全局常量名: 全部使用大写字母和下划线,下划线用来分隔单词 如:
CONST_NAME
变量名/参数名: 使用小写字母、数字、下划线的组合,且不以数字下划线开头 如:
var_name
方法名/函数名: 使用小写字母、数字、下划线的组合,且不以数字下划线开头 如:
method_name()
Python习惯称在类内的函数叫方法,不在类内的叫函数
Python对于缩进有这严格的语法要求,错误的缩进可能会导致错误,这也是它的语法特点
建议用4个空格进行缩进,而不要使用Tab(设置Tab键为4个空格时可以使用)
不要在行尾加分号,也不要用分号将两条语句放在同一行
每行不超过80个字符
不要使用反斜杠连接行,可以使用圆括号来进行隐式行连接,就像这样
str = ("如果一个文本字符串在一行放不下" "可以使用圆括号来进行隐式行连接")
不要在逗号、分号、冒号的前面加空格,但应该在他们的后面加空格(除了行尾)
二元操作符两边各加一个空格,当 = 用于关键字参数或默认参数,不要在两侧加空格
注释以非字符串面值的字符(#)开始,在物理行的末尾结束,执行Python会忽略这些注释,使用三引号可作多行注释
# 这是单行注释 print(‘Hello,World!‘) """ 这是多行注释,可以写很多很多行的功能说明 下面的代码完成 ,打印一首诗 名字叫做:佛祖镇楼 """ print(" _ooOoo_ ") print(" o8888888o ") print(" 88 . 88 ") print(" (| -_- |) ") print(" O\\ = /O ") print(" ____/`---‘\\____ ") print(" . ‘ \\| |// `. ") print(" / \\||| : |||// \\ ") print(" / _||||| -:- |||||- \\ ") print(" | | \\\\\\ - /// | | ") print(" | \\_| ‘‘\\---/‘‘ | | ") print(" \\ .-\\__ `-` ___/-. / ") print(" ___`. .‘ /--.--\\ `. . __ ") print(" ."" ‘< `.___\\_<|>_/___.‘ >‘"". ") print(" | | : `- \\`.;`\\ _ /`;.`/ - ` : | | ") print(" \\ \\ `-. \\_ __\\ /__ _/ .-` / / ") print(" ======`-.____`-.___\\_____/___.-`____.-‘====== ") print(" `=---=‘ ") print(" ") print(" ............................................. ") print(" 佛祖镇楼 BUG辟易 ") print(" 佛曰: ") print(" 写字楼里写字间,写字间里程序员; ") print(" 程序人员写程序,又拿程序换酒钱。 ") print(" 酒醒只在网上坐,酒醉还来网下眠; ") print(" 酒醉酒醒日复日,网上网下年复年。 ") print(" 但愿老死电脑间,不愿鞠躬老板前; ") print(" 奔驰宝马贵者趣,公交自行程序员。 ") print(" 别人笑我忒疯癫,我笑自己命太贱; ") print(" 不见满街漂亮妹,哪个归得程序员?")
#!/usr/bin/python3 """ Author : Jet Bi License : www.cyeap.com Summary : 摘要信息 Notes : 提示信息 """
Python操作运算符
- 有关位操作的操作符的参数必须是整数类型
- 比较操作符的结果只会产生两个值
True
和False
- 布尔操作符(逻辑运算符)的参数不仅限于
True
和False
,如果使用布尔操作符活if
、while
的条件表达式等,以下值将被视为假False
(真值测试)- False
- None
- 任何数值类型的零,如:
0
0L
0.0
0J
- 任何空的序列类型,如:
" "
[]
()
- 任何空的映射类型,如:
{}
- 布尔操作符的运算规则如下
- 如果not的参数为假,则返回
True
,否则返回False
- 表达式
x and y
首先计算x
;如果x
为假,则返回False
;否则,再计算y
并返回结果的值 - 表达式
x or y
首先计算x
;如果x
为真,则返回True
;否则,再计算y
并返回结果的值
- 如果not的参数为假,则返回
# 一元算术运算符 # - 负 + 正(+号一般忽略不写) # 一元位运算符 # ~ 按位取反 # 二元算术运算符 # + 加法 - 减法 * 乘法 / 除法 % 取模 ** 取幂 // 取整除 # 二元位运算符 # & 按位与 | 按位或 ^ 按位异或 # 位移操作符 # << 左移动 >> 右移动 # 比较操作符 # < 小于 <= 小于等于 > 大于 >= 大于等于 == 等于 != 不等于 # is 相同对象ID is not 不同的对象ID # in 在序列中 not in 不在序列中 # 布尔操作符(逻辑运算符) # and 与 or 或 not 非 # 条件表达式(三元操作符) # Python中的三元操作符具有最低的优先级,其语法格式如下: # x if C else y # 表达式首先计算条件C,如果C为True,则计算x并返回它的值;否则,计算y并返回它的值 # Lambda表达式 # Lambda表达式(有时叫做lambda形式)具有和表达式相同的地位,它们是创建匿名函数的一种快捷方式: # lambda [arg1 [,arg2,...argn]]:expression
Python语言参考
# 赋值语句 # 赋值语句用于(重新)绑定名称到具体的值以及修改可变对象的属性或元素 # = # 增强的赋值是将二元操作和赋值语句组合成一个单一的语句 # += -= *= /= %= **= //= 如: x += 1 等价于 x = x + 1 # assert语句(断言) # assert语句是插入调试断言到程序中的一种便捷方法,即如果断言的表达式不为True,则会引发异常 # assert expression[, errorinfo] # 注: # 1.如果expression为真,则不执行任何操作,否则,引发AssertionError # 2.可以加入errorinfo,以便获取更多的错误信息 # break语句 # break在语法上只可以出现在for或者while循环中,但不能嵌套在这些循环内的函数和类定义中,用来终止循环 # 注: # 当break将控制传出带有finally子句的try语句时,在离开循环之前会执行finally子句 # continue语句 # continue在语法上只可以出现在for或while循环中,但不能嵌套在这些循环内的函数定义、类定义和finally子句中,它继续最内层循环的下一轮 # 注: # 当continue将控制传出带有finally子句的try语句时,在真正开始下一轮循环之前会执行finally子句 # class类定义 # Python从设计之初就已经是一门面向对象的语言 # 正因为如此,在Python中创建一个类和对象是很容易的,具体Python面向对象的内容就不赘述了 # def函数定义语句 # 1.函数定义是一个可执行的语句,它的执行将绑定当前局部命名空间中的函数名到一个函数对象(函数可执行代码的封装) # 2.函数定义不会执行函数体,它只有在调用函数的时候才执行 # del语句 # 1.删除目标将从左向右递归删除每一个目标。 # 2.删除一个名称将从局部或全局命名空间中删除该名称的绑定,取决于名称是否出现在相同代码块的global语句中 # 3.如果名称没有绑定,将抛出一个NameError 异常 # global语句 # 1.global语句是针对当前整个代码块的声明,它的意思是列举出来的标识符要解释为全局的 # 2.不用global给全局变量赋值是不可能实现的,尽管自由变量可以引用全局变量而不用声明为全局的 # 3.在相同的代码块中,global语句中列出的名称不可以在global语句之前使用 # 4.global语句列出的名称不可定义为形式参数或者定义在for循环的控制目标、类定义、函数定义或import语句中 # import语句 # import语句的作用是导入包或模块,分两步执行: # 1.找到模块,如果必要则进行初始化 # 2.定义(import语句所在作用域的)局部命名空间中的名称,该语句有两种形式 # 第一种形式 # import module[as name][, module [as name]] # 第二种形式 # from module import * # pass语句 # pass是一个空操作,执行它的时候,什么都不会发生,它的主要用处是为了保持语法结构的完整性 # print语句 # 1.依次计算每一个表达式并将求得的对象写入标准输出 # 2.如果对象不是字符串,那么首先使用字符串转换规则将它转换成字符串,然后输出 # 3.在结尾会写入一个‘\n‘字符,如果想让print不换行,python2中在末尾加逗号,python3中print("Hello", end="") # return语句 # return语句用来返回函数的返回值 # return [expression_list] # 注: # 1.return在语法上只可以出现在函数定义中,不可以出现在类定义中 # 2.如果存在expression_list,则计算它,否则使用None替换 # 3.return离开当前的函数调用时以expression_list(或None)作为返回值 # 4.当return将控制传出带有finally子句的try语句时,在真正离开函数之前会执行finally子句 # raise语句 # raise用来手动触发异常,其语法格式如下: # raise [expression [, expression[, expression]]] # 注: # 1.如果第一个对象是一个实例,那么异常的类型是实例的类,实例本身是值,第二个对象必须是None # 2.如果第一个对象是一个类,那么它将成为异常的类型,第二个对象用于决定异常的值: 如果它是类的实例,那么该实例将成为异常的值 # 3.如果第二个对象是一个元组,它用于类构造函数的参数列表 # 4.如果它是None,则使用一个空的参数列表,如果是其它任何对象则被当做构造函数的一个单一的参数 # 垃圾回收 # Python 使用了引用计数这一简单技术来跟踪和回收垃圾,在 Python 内部记录着所有使用中的对象各有多少引用。 # 一个内部跟踪变量,称为一个引用计数器。 # 当对象被创建时,就创建了一个引用计数,当这个对象不再需要时,也就是说,这个对象的引用计数变为0时 # 它被垃圾回收,但是回收不是"立即"的,由解释器在适当的时机,将垃圾对象占用的内存空间回收 # 垃圾回收机制不仅针对引用计数为0的对象,同样也可以处理循环引用的情况
流程控制
if判断语句
# 语法1: # if 条件判断式: # 当条件判断式成立时,执行的语句 # 语法2: # if 条件判断式: # 当条件判断式成立时,执行的语句 # else: # 当条件判断式不成立时,执行的语句 # 语法3: # if 条件判断式一: # 当条件判断式一成立时候,执行的语句 # elif 条件判断式二: # 当条件判断式二成立时候,执行的语句 # ... # elif 条件判断是N: # 当条件判断式N成立时候,执行的语句 # else: # 当以上所有条件判断式均不成立时,执行的语句 i = 0 if type(i) is not int: print(‘非整数类型‘) elif i < 0: print(‘小于0‘) elif i > 0: print(‘大于0‘) else: print(‘等于0‘)
while循环语句
# 语法1: # while 条件判断式: # 当条件判断式成立时,循环执行的语句 # 语法2: # while 条件判断式: # 当条件判断式成立时,循环执行的语句 # else: # 当循环正常执行完毕之后(即不是通过break跳出而中断的),执行的语句 i = 0 while i < 9: print(‘ # ‘ * i) i += 1
for循环语句
# Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串 # 语法1: # for 项 in 序列: # 当"项"在"序列"中时,循环执行的语句 # 语法2: # for 项 in 序列: # 当"项"在"序列"中时,循环执行的语句 # else: # 当循环正常执行完毕之后(即不是通过break跳出而中断的),执行的语句 # 示例1: for循环遍历字符串 for letter in "Python": print(letter) # 示例2: for循环遍历列表 l = [1, 2, 3, 4, 5, 6] for item in l: print(item) # 示例3: for循环遍历列表,带下标 l = [1, 2, 3, 4, 5, 6] for index, item in enumerate(l): print(index, item) # 示例4: for循环遍历字典 key(键) d = {1: "one", 2: "two", 3: "three", 4: "four", 5: "five"} for key in d.keys(): print(d[key]) # 示例5: for循环遍历字典 value(值) d = {1: "one", 2: "two", 3: "three", 4: "four", 5: "five"} for v in d.values(): print(v) # 示例6: for循环遍历字典 key-value(键值对) d = {1: "one", 2: "two", 3: "three", 4: "four", 5: "five"} for k, v in d.items(): print(k, v) # 示例7: for循环遍历序列 for i in range(10): print(i) # continue 跳出所在循环体的当前循环进入下一次循环 # break 结束所在循环体的整个循环 # 示例1:循环打印0-9的时候,不打印5 for i in range(10): if i == 5: continue print(i) # 示例2:循环打印列表中的数字,如果遇到不是整数类型则结束打印 l = [1, 2, 3, 4, ‘五‘, 6, 7, 8, ] for i in l: if type(i) != int: print(f‘遇到了非整数元素:{i},结束打印‘) break print(i)
try 异常处理
# 如果你不想在异常发生时,结束你的程序,只需在try里捕获它 # 语法1: # try: # 正常执行的代码 # except 异常A: # 如果在try部分引发了异常A,将会执行这里的代码 # except 异常B, B的异常信息: # 如果在try部分引发了异常B,将会执行这里的代码,并能够获得附加异常信息 # except (异常C, 异常D): # 如果引发了异常C和异常D将会执行这里的代码 # except Exception as ex: # 如果引发了异常A,B,C,D之外的异常将会执行这里的代码 # else: # 如果没有异常发生还可以在执行一下这里的代码 # 语法2: # try: # 正常执行的代码 # except Exception as ex: # 如果发生异常执行的代码 # finally: # 无论是否发生异常都要执行的代码 # ------------------------------------------------------------------------------- # 示例1: TypeError异常捕获 num = 10 try: print("字符串+数字 不转换会有异常" + num) except TypeError as ex: print(f"你看看,报异常了吧!{ex}") # 示例2: TypeError异常触发 num = 10 try: print("字符串+数字 不转换会有异常" + str(num)) print("你以为这样就结束了吗?看我触发异常!") raise TypeError("可以自定义异常信息!") except Exception as ex: print("你看看,依然报异常了吧!" + str(ex)) finally: print("无论异常是否发生都会会执行这里!")
常用数据类型
数值类型
int 整数类型 整数使用C中的long实现,拥有准确的精度,此外布尔类型是整数类型的子类型,True=1 False=0 float 浮点数类型 浮点数使用C中的double实现,Python放弃了单精度浮点型,float总是不精确的,所以不要用于金钱 complex 复数类型 复数由实数与虚数构成,是数的概念扩展,在数值的后面加 ‘J‘ 或 ‘j‘ 进行定义,不常用 # Python3中的长整型long和整型int已经统一成了int类型,所以long类型与其相关的函数,已不存在 # 标准库包括了额外的数值类型还有 decimal(支持自定义精度的浮点型,可以用于金钱计算)、fractions(包含了有理数)等 # Python完全支持混合算数,当不同数值类型的算数时,具有"较窄"类型的操作数会被加宽到另一个操作数 # Python定义 pow(0, 0) 和 0 ** 0 为1,这对于编程语言很常见 # Python3中的round()函数,如果距离两边一样远,会保留到偶数的一边。如 round(4.5) = 4, round(5.5) = 6
序列类型
str 文本序列类型(字符串) # 单引号和双引号没有啥特别的区别,有个好处就是在单双引号嵌套时,不用在进行转义了 # 三引号,使用一对 ‘‘‘三个单引号‘‘‘ 或 """三双引号""",三引号字符串可以跨越多行,所见即所得 # Python3中默认采用unicode字符 # 字符串前面加个r代表原生字符,里面的转义字符将失效,多用于正则表达式 # 字符串前面加个b代表二进制字符串为字节对象 bytes # Python3.6版本之后支持使用新的字符串格式化方式 即: f"Hello,{name}" # 字符串是不可变的序列,一旦创建不能修改,通过方法返回的字符串只是其副本 list列表 和 tuple元组 # list对象使用一对方括号[]进行定义,各元素之间用逗号 , 进行分隔,元素可以重复 # 下标可以访问list对象中的元素,因此list对象是有序的 # list对象属于可变序列类型,使用list中的方法对list对象进行操作时,往往会改变其本身的值 # 在修改列表的时候,列表中其他的元素可能会发生位置的偏移 # tuple对象相当与一个只读的list对象,使用一对圆括号()定义,元组中的元素不可以改变,但不包括元组中元素的元素 # 在定义list和tuple对象的时候,最好在最后一个元素的后面加一个逗号 , # 在遍历列表的时候不要修改列表中的值,否则有可能乱序,如果需要循环修改列表,请循环该列表的长度即:for i in range(len(l)):... range 范围类型 # range(start, stop, [, step]) 创建一个整数列表,一般用于for循环之中 print(list(range(10))) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] print(list(range(1, 10))) # [1, 2, 3, 4, 5, 6, 7, 8, 9] print(list(range(1, 10, 2))) # [1, 3, 5, 7, 9] print(list(rang(9, 0, -1) # [9, 8, 7, 6, 5, 4, 3, 2, 1] bytes、bytearray、memoryview 二进制序列类型 bytes # 字节组成的有序的不可改变序列(区别:字符串是字符组成的序列,以一个字符为单位;字节序列是字节组成的序列,以字节为单位) bytearray # bytes类型的可变版本 memoryview # 提供了统一且安全的直接读或者写内存的途径。python里一切都是对象,而且简单的字符串操作都会引起内存拷贝和新对象的产生。memoryview正为减少内存拷贝,优化效率而来。 # 序列访问 # 序列类型是有顺序的,可以通过索引(或者说下标)访问序列中的元素 # 1.从左到右索引默认是从0开始的,最大范围是: 序列长度-1 # 字符串: Hello! # 下 标: 012345 # 2.从右到左索引默认是从-1开始的,最大范围是: 序列的开头 # 字符串: Hello! # 下 标: (-)654321 # 序列切片 # 序列类型支持切片操作,以字符串为例 # 切片语法 # seq[i:j] # seq[i:j:k] # 注: # 1.i,j为数字表示开始下标和结束下标,截取结果包含开始下标对应的项,不包含结束下标对应的项 # 2.k为数字表示步长,默认为1,也就是说是可以跳着切片的 # 3.i,j,k可以不写,不写的话就取默认值 s = "0123456789" s[3] # 返回下标为3的字符,即: 3 s[3:] # 返回下标3至结尾的字符,即:3456789 s[-1] # 返回下标为-1的字符,即: 7 s[:-1] # 返回下标为开头至-1(不含)的字符,即: 012345678 s[3:5] # 返回下标从3到5(不含)之间的字符,即34 s[0::3] # 返回全部字符串中每三个为一组的首个字符的组合,3表示步长,即0369 s[::-1] # 从尾部开始切片,即9876543210
映射类型
dict 字典类型 # dict是标准的映射类型,字典是可变对象,采用键值对的方式存储数据 # 字典的键必须是不可变类型的值(比如列表,字典等类型是不可以用作键),且不可重复(重复会覆盖) # 字典的值则几乎是任意的值,且可以重复 # 浮点数虽然可以作为键,但强烈不推荐这样做(因为计算机存储的是浮点数的近似值),推荐用字符串作为键 # 字典是无序的元素集合 # in 对字典操作时,判断的是字典的键
集合类型
set 可变集合 # 可添加和删除元素,它是不可哈希的,因此set对象不能用作字典的键或另一个元素的集合 forzenset 不可变集合 # 正好与set相反,其内容创建后不能更改,它是不可改变的集合,是可哈希的 # set 集合是一组无序的且不可重复的元素的集合,访问速度较快 # set 的构造参数需要一个序列对象,这个序列可以是可变类型,但序列中的元素必须是不可变类型(即可哈希的) # 集合支持类似其他容器的len(set)、for x in set ,但不支持索引、切片或其他类似序列的行为 # 列表的快速去重 l = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5] s = set(l) print(s) # 输出结果: {1, 2, 3, 4, 5}
函数
# Python3中的函数定义 # def 函数名([参数列表]): # 函数体 # [return 返回值] # 注: # 1.类外的def定义的叫函数,类内的def定义的叫方法 # 2.方法和函数都有返回值,不写return,默认返回None # # Python3不同参数函数的定义与调用 # 示例1.无参数 def print_hello(): print("Hello!") # 函数调用 print_hello() # 示例2.必备参数 def print_article(title, content): print(f"文章标题:{title}") print(f"文章内容:{content}") # 函数调用 title = "世界上最好的计算机语言" content = "PHP是世界上最好的语言" print_article(title, content) # 1.通过参数位置来传递参数(必须按照顺序) print_article(content=content, title=title) # 2.通过参数名称来传递参数(可以不按照顺序) # 示例3.缺省参数(默认值参数) def print_article(t="默认标题", c="默认内容"): print(f"文章标题:{title}") print(f"文章内容:{content}") # 函数调用 title = "世界上最好的计算机语言" content = "PHP是世界上最好的语言" print_article() # 1,可以不传递参数,则取默认值 print_article(title, content) # 2.可以传递参数,默认值将被替换 # 示例4.动态参数(不定长参数) def print_args(*args, **kwargs): print(f"一个*的args会自动转换成元组{type(args)}") print(f"参数内容{str(args)}") print(f"两个*的kwargs会自动转换成字典{type(kwargs)}") print(f"参数内容{kwargs}") # 函数调用 # 传递的时候先传位置参数,这些参数会被自动转换成一个列表 # 再传名称形式的参数,这些参数会被自动转换成一个字典 print_args(1, 2, 3, 4, one="1", two="2") # 如果想直接传递整个列表或字典需要在参数前面加对应的 * l = [2, 3, "哈哈", ] d = {"one": "1", "two": "2", "Jet": "Good Boy!"} print_args(*l, **d)
模块
简单的说, 模块就是一个保存了一大堆Python代码的文件, 模块能定义函数, 类和变量, 也能包含可执行的代码, 一个叫做module_name的模块里的代码一般都能在一个叫module_name.py的文件中找到
模块的搜索顺序,当你导入一个模块, Python解释器对搜索该模块的位置顺序是(在sys.path中可以看到):
- 程序运行的当前目录查找
- 搜索PYTHONPATH环境变量设置的目录
- 查找标准库目录(Unix下, 默认路径一般为 /user/local/lib/python)
- 根据.pth文件内容进行查找(一般放在Lib\site-pachages目录下)
- 临时加载的工作路径 sys.path.append(‘d:\test‘)
模块的导入
- 导入整个模块的内容
import module_name
- 导入模块的部分内容
from module_name import obj_name
面向对象
Python从一开始设计就是面向对象的,并且结构上支持OOP,但Python并不会强制你写面向对象的代码,面向对象是一中概念性的东西,讲的是Everything is object,通过面向对象思想写出来的程序具有更好的扩展性,这个东西需要通过不断的编程,进行经验的积累,才能进行深入理解
类和对象
# 类是具备某些共同特征的实体集合,是一种抽象的数据类型,类是对象的模板 # 类中的静态特征称之为属性 # 类中的动态特征称之为方法 class CalssName(object): pass # 对象是类的实例 zhangsan = Person() # 创建人类的实例张三, 这叫类的实例化, zhangsan 即为 Person 类实例化出来的对象
- Python2.x 默认都是经典类,只有现实继承了object才是新式类
- Python3.x 默认都是新式类,废除了经典类
- 新式类和经典类的最大区别就在于继承搜索的顺序不同:
- 新式类(广度优先)
- 经典类(深度优先)
封装
- 封装隐藏类的实现细节,避免用户通过不规范的操作来存取封装的数据属性
- 将属性和方法放到一起作为一个整体,然后通过实例化对象来处理
- 对类的属性和方法增加访问权限控制
继承
继承最主要的功能是代码的复用,Python支持多继承,所有类的顶级父类是object
在继承中父类的构造方法__init__()不会被自动调用,需要在子类中手动调用
Python支持多重继承
父类私有的属性和方法不会被子类继承
class Father(object): def talk(self): print("I‘m Laowang, My name is %s" % self.name) class LaoWang(object): def __init__(self, name): print("This is LaoWang") self.name = name # 实例变量属于实例,不属于类 def papapa(self): print("Pa pa pa...") class Child(Father, LaoWang): def __init__(self): # super()代表他所有的父类,当调用__init__方法的时候,它会先找Father,Father中没有,在找的Laowang # 查找算法叫做MRO,即广度优先 super().__init__("Jet") super().papapa() # 实例化 child = Child() child.talk()
多态
Pyhon不支持多态,换句话说,Python本身就是“多态”的,因为它是弱类型语言,对象的类型由Python解释器自动识别转换。所谓多态:定义时的类型和运行时的类型不一样,此时就成为多态,多态的概念是应用于Java和C#这一类强类型语言的,而Python崇尚“鸭子类型”,即:虽然我想要一只鸭子,但是你给了我一只鸟。只要这只鸟走路像鸭子,叫的像鸭子,游泳也像鸭子,我就认为这是鸭子。Python的多态,就是弱化类型,重点在于对象参数是否有指定的属性和方法,如果有就认为合适,而不关心对象的类型是否正确。
关于访问修饰符
Python中没有类似于Java中的private、protected、public这样的特定关键字,是使用特殊写法来进行区分访问权限的
private[Java]: __xxx
- 这样的属性与方法就相当于私有的,不能类外部直接访问
protected[Java]: _xxx
- 这样的属性与方法就相当于受保护的,但是按照约定俗成的规定,是可以被类外部直接访问的
- 但是,当你看到这样的变量时,意思是"虽然我可以被访问,但是请把我视为私有变量,不要随意访问"
public[Java]: xxx
- 默认的,不带下划线的,都属于公共的,可以随意访问
注意事项
类似于__xxx__这样写法的属性和方法是特殊变量,特殊变量是可以直接访问的,不是private变量,Python保留的命名
Python的私有变量__xxx是不是一定不能从外部访问呢?其实也不是,我们可以通过这样的方式来进行访问
实例对象._类名__xxx
但是,强烈不建议你这么干,因为不同版本的Python解释器可能会把xxx改成不同的变量名
总的来说,Python本身没有任何机制阻止你干坏事,一些全靠自觉
访问权限的规则和Java差不多,能用小的权限,就不要用大的