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!

环境搭建

  • 下载安装并配置镜像源
  • 注意添加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

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操作运算符

  • 有关位操作的操作符的参数必须是整数类型
  • 比较操作符的结果只会产生两个值TrueFalse
  • 布尔操作符(逻辑运算符)的参数不仅限于TrueFalse,如果使用布尔操作符活ifwhile的条件表达式等,以下值将被视为假False(真值测试)
    • False
    • None
    • 任何数值类型的零,如: 0 0L 0.0 0J
    • 任何空的序列类型,如: " " [] ()
    • 任何空的映射类型,如: {}
  • 布尔操作符的运算规则如下
    1. 如果not的参数为假,则返回True,否则返回False
    2. 表达式 x and y 首先计算x;如果x为假,则返回False;否则,再计算y 并返回结果的值
    3. 表达式x or y 首先计算x;如果x为真,则返回True;否则,再计算y 并返回结果的值
# 一元算术运算符
#    - 负    + 正(+号一般忽略不写)
# 一元位运算符
#    ~ 按位取反
# 二元算术运算符
#     + 加法  - 减法  * 乘法  / 除法  % 取模  ** 取幂  // 取整除
# 二元位运算符
#     & 按位与  | 按位或  ^ 按位异或
# 位移操作符
#     << 左移动  >> 右移动
# 比较操作符
#     < 小于  <= 小于等于  > 大于  >= 大于等于 == 等于 != 不等于
#     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中可以看到):

  1. 程序运行的当前目录查找
  2. 搜索PYTHONPATH环境变量设置的目录
  3. 查找标准库目录(Unix下, 默认路径一般为 /user/local/lib/python)
  4. 根据.pth文件内容进行查找(一般放在Lib\site-pachages目录下)
  5. 临时加载的工作路径 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差不多,能用小的权限,就不要用大的

相关推荐