- Python的历史
- 环境搭建
- Python编码规范
- Python操作运算符
- Python语言参考
- 流程控制
- if判断语句
- while循环语句
- for循环语句
- try 异常处理
- 常用数据类型
- 数值类型
- 序列类型
- 映射类型
- 集合类型
- 函数
- 模块
- 面向对象
- 类和对象
- 封装
- 继承
- 多态
- 关于访问修饰符
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差不多,能用小的权限,就不要用大的