python编程笔记

python编程

第一章 用户交互

编程,让机器取代人力

编程语言:机器语言(二进制1/0)快但开发效率低;汇编语言(用简单的英文取代部分机器码)效率有所提升但还是要转成机器码执行执行效率降低;高级语言(用英语编程,建立在操作系统之上的语言)操作系统做了个封装,把硬件操作封装成一个接口。
‘用高级语言执行效率低但在发展上却是是进步的,因为执行速度是从0.000000001变成0.00001,而开发效率提升所节省的时间是非常明显的’

高级语言分类

高级语言最终都会转换成机器语言执行,按照转换方式可以分为两种语言:
编译型:c/c++为例子,编译型语言通过编译器直接一次性编译成机器码供操作系统统一执行(不同的操作系统会编译成不同的机器码,因为提供的硬件接口不同所以机器码也不同),执行速度快,依赖于编译器,但调试麻烦,适用于编写操作系统或底层应用等不经常改变或升级的代码。
解释型:如python、php,需要依赖解释器。经过编译后成为字节码,在虚拟机中解释(翻译为机器码)一句执行(给操作系统执行)一句,先编译为字节码文件(各操作系统都一样),然后交给虚拟机(各操作系统不一样的虚拟机,在这里实现跨平台)执行。调试方便灵活,适用常变动的应用如app或网站。python的简洁且高度封装性常用于快速开发和迭代的新项目中,即可写app接口又可写web和机器学习算法及数据挖掘。

在这里插入图片描述

python相关介绍

IDE(集成开发环境):写代码的工具。常用的有jupyter notebook 不适合做工程,但是做数据分析,建模很方便清晰,用这个来学习python很不错。
pycharm 开发工程项目IDE,使用友好,用户多。

python应用领域:
web开发—django/flask框架适用于创业型公司快速简历产品业务逻辑。
网络编程—支持高并发的Twisted网络框架使异步编程变得非常简单。
爬虫开发—爬虫领域的霸主地位丰富的框架及库可以轻松获取网上几乎所有资源。
云计算,人工智能,自动化运维,数据分析,科学计算,自动化测试,游戏开发等。

解释器交互模式:调试方便,无法永久保存
脚本文件方式:永久保存

注意事项

匈牙利命名法:变量命名规范,把变量类型缩写翻到变量名的最前面。可以粗略判断出一个人的水平。
写代码先捋清逻辑关系,可先写伪代码(中文或英文字符串占位)在用正确语法格式实现。
匈牙利命名法

数据类型知识

不可变类型:但变量值改变时,id也会跟着一起变化,相当于重开一块内存空间;要装修只能盖新房装修,不能在旧房装修。可读不可写
可变类型:值变id不变,可在旧房装修,可读可写。

变量

计算机工作的过程就是对数据的增删改查,需要变量来保存变化的数据。
变量名能表清逻辑及含义,格式:关键词不能做变量名,开头不能喂为数字,有字母,数字,下划线组合。驼峰体,或者下划线。如name_list,NameList
变量三要素:id(逻辑存储位置),type,value(具体值)
但两变量name1与name2的value比较短且相同时,python会自动进行资源优化,将name1和name2开启同一个内存空间 name1 is name2返回True,但值很长或不同时时为False

常量

格式:全为大写。

注释

在大工程中需要在自己觉得重要或者不好理解的地方加注释;注释用中文或英文,不要中英混。
写规范注释是代表一位程序员素养最简单的方式。

文件头

文件头:文件顶部记录开发规范的细节
可以在pycharm里配置好,每次新建脚本就会自动添加文件头。具体操作:从preferences–Editor–File and Code Templates–Python Script里找到一块空白的区域,填入以下内容。把作者改成自己的名字,其他的都是变量,会自动根据创建状态生成在这里插入图片描述

用户交互

python3的input输入的都是字符串类型
python2中的input输入什么类型就是什么类型,其raw_input作用等同于python3中的input

第二章 流程控制

流程控制用法注意

避免多次分支嵌套:俗称“嵌套if地狱”
封装复杂逻辑判断:条件分支里的条件表达式如果太多not/and/or,解决方法是拆解或者用 not 取反
留意不同分支下的重复代码:编写条件分支语句时要特别留意不要产生不必要的重复代码,重复代码是代码质量的天敌。
使用德摩根定律:A:没有余额;B:没有登录 not A or not B:print(‘拒绝购买’) 等价于 not (A and B): print(‘拒绝购买’),必须登录且有余额才能购买,使代码表达更接近人的逻辑。
在条件判断中使用 all(seq) /any(seq) :seq序列中有全为True时,则 all() 才返回True;seq序列中有有一个为True时,则 any() 就返回True.
使用 try/while/for 中的else分支可以简化代码,如try中要执行第一个函数成功后再执行第二个函数,如果不用else就要加个标志来判断第一个函数是否执行成功,用else就不用,直接将第二个函数放入其中,try成功后会自动执行else中的第二个函数。
与None值比较是用 is ,因为 is 比较唯一的id,==比较值。
留意 and 和 or 的优先级,and的优先级大于 or,意义通过加()使逻辑更清晰。

CPU有两个功能,控制和运算。
有些数据类型是自带布尔值的,如none,‘’的布尔值为false。
时间就是死循环,不停的购物就是有效死循环,无效的死循环会占用资源。
while使用如用户回答正确则break,错误则continue。

if,elif,else的使用:
if A:      # 如果A
	pass
elif B:    #如果非A且B
	pass
else C:    #如果非A且非B
	pass
while 的使用:

在有些场景下需要反复验证某种情况时使用,如验证用户名与密码,无法判断输入次数是用条件循环while。
while和else的组合使用:
在while循环体后面加了else,如果在while中没有被break终止的话,就会执行else的语句,常用于通知while中的任务结束。

count=0
while count <= 5:
	count+=1
else:
	print('程序执行完毕!!!')
for 循环:

range(10)顾头不顾尾(0-9)

for var_name in iteration:
	pass

for和else的组合使用:
如同while与else;都是循环非break结束后执行else中的语句

第三章 数据类型

数值很大的整型会转成字符串存储来节省内存
不可变类型可以哈希,可变类型不可以哈希
str中的组合跟split是相反的‘ ’.join(seq)组合seq用‘ ’间隔。
元组比列表占用更少的内存空间,列表元组最重要
用集合不仅去重更重要的是做关系运算

列表赋值与深浅拷贝(copy)总结:赋值相当于添加了一个引用(id指向name,name引用了内存空间中的数据),并没有开辟新的内存空间。
浅拷贝:复制原对象的一级元素引用,对象本身新开辟内存空间,对内部可变型子元素只能进行删除(会只删除引用),否则其他操作则会改变所有引用了同一个内存空间的对象元素的值。
深拷贝:不复制任何引用,直接复制原对象的所有N级数据,为所有数据开辟新的内存空间。

浅拷贝
元组是不可变类型,主要用来读,用于存储多个值,可用于做字典的key。

python自带的容器数据类型

更高级更方便的collections容器数据类型,可查阅官方文档
namedtuple命名元组:元组名及元组里的元素也有名,有更高的指向性。
deque超级列表:数据结构中的双向队列可以在deque中实现,deque支持在list容器的两端进行快速的添加(append)和弹出(pop)
ChainMap链映射:将多个映射快速的连接到一起,这样就可以当做一个单元来处理。
链映射介绍
链映射使用
Counter 计数字典:自动创建要计数的key,用普通字典要先建立含计数key的字典。
计数字典使用

第四章 字符编码(一行代码背后的故事)

参与硬件:CPU,内存,硬盘
顺序:应用软件下载存放到硬盘中,软件从硬盘中加载到内存中运行,CPU调用内存中的数据进行处理计算。例如执行python程序的过程,将python解释器读入内存再将编写的.py文件读入内存,然后用python解释器识别python语法解释执行.py文件。离开了python解释器的.py文件就是普通文件 ,你可以用任何编辑器取编写代码甚至2是WPS,只不过IDE有代码自动提示及语法检测的功能。只有在最后的解释器解释执行python程序的时候才会检测语法。

字符编码:每一个字符根据字符编码表转化成一组二进制数字存储在计算机的内存和硬盘中。
字符编码表:存放在内存之中,每个国家的文字不同所以字符及字符编码表(中国GBK,日本Shirt-JIS,韩国Euc-kr,美国-ASCII)也不一样,为了使不同国家之间的程序可以相互运行出了同一的字符编码表Unicode编码,通过Unicode作为中间编码,负责与其他各国的编码转换。
但是由于Unicode编码的字符长度是固定的,造成了不必要的I/O开销,所以现在内存和硬盘都是用变长的Unicode编码即utf-8.

解决乱码的方法:用什么编码写入硬盘就用什么编码读出硬盘。

windows及python2的默认编码时gbk,而python3和MacOs,linux的默认编码都是utf-8

Unicode编码转换过程
Unicode与其他字符码编码解码过程
在这里插入图片描述

第五章 文件处理

文件操作流程

底层硬件
操作系统
应用程序
将程序产生在内存的数据永久保存到硬盘中,调硬盘接口与操作系统交互,依赖操作系统操作硬件。
open是python通过操作系统打开文件的接口,打开文件的默认编码格式为操作系统默认编码格式。打开接口完成任务后要关闭接口,解除操作系统的资源占用,因为操作系统打开文件夹的数量也是有限的,不关闭就和一直占用,就跟你图形操作界面打开文件夹不关闭一样。
三个参数(文件路径,打开模式,读写编码格式)
打开模式:有两种模式,一种是默认的 t 文本模式,以字符形式存储读写不转二进制,方便操作文本,所以不能打开图片及音频文件。文本模式下有三种子模式(rt,wt,at-t是默认,所以经常可以省略,只读,只写,追加写);另一种则是 b (必须是rb,wb,ab不可省略b)二进制模式,b模式也可以读取文本,只不过是从二进制读过来,而t模式则在open的时候已经将二进制转化为了文本,这也是t的方便之处,但图片音频不能转文本。

文件内光标移动
打开文件时会有一个光标移动扫描文件,可以通过seek(num)方法来以字节为单位来改变偏移量来读取文件。

第六章 函数概述

先定义再调用。具备某一个功能的工具就是函数。
函数名字:必须能反应函数的功能,是动词或者动词词组,函数是一个动作功能。
文档注释注释该函数的功能来增强函数的可读性

#函数作用
def func1(x,y):
"""
x   xxxx
y   xxxx
return xxx
"""

三种形式:有参函数,无参函数,空函数
定义空函数,实现功能组织结构,通过调用函数执行某个功能,定义好功能规划项目结构
定义时不执行函数里的代码,调用时才执行。
函数是否有返回值根据函数的逻辑有无处理结果返回来决定。
return 标志函数已经结束了

函数的参数

形参:其实就是变量名,定义函数是括号内的参数。
实参:变量的值,就是函数调用时传入的值。
形参和实参之间的绑定只有在函数调用时才会生效,函数调用结束后就立刻解除绑定。

五种传参方式:
位置参数(x,y,z):调用函数时必须传值且数量相同。
关键字参数(x,y,z):位置实参必须放在关键字实参前面,且一个形参只能一种传值,实参与形参个数还是要同。
默认参数(x,y,z=1):同样位置实参必须放在默认实参前面相比于关键字,默认值要先设定且同样要指定形参名传参,可以不传即实参和形参个数可以不同。
可变长参数 (x,y,z,* args) /(x,y,z,**kwargs):将多余的实参全部赋args成元组/kwargs成字典,通过星号将其打散,实参加星号就是把星号后面的变量打散成序列或字典。
星与星星号应用场景:求打包序列中的累计和,或一个用户的各项信息拆分成字典。
组合使用:直接将所有参数传给函数中调用的函数,而其调用的函数可以值接收自己需要的参数。
星与星星的组合使用在源码中非常常见,也是装饰器的核心之一,着非常重要。
命名关键字参数:
核心是*号,args变量名有或没有都不影响,在星后面的都是命名关键字参数,必须被传值,传入的参数必须是以key=value的形式。

*args示例
**kwargs示例
*args与**kwargs的应用场景
组合使用示例
命名关键字参数示例

第七章 闭包函数

每个函数对应一个功能(工程化思维),尽量避免 if-else 分支
名称空间:存放变量名与变量值绑定关系的地方,简称变量。
有三种:内置变量(python自带的变量,解释器启动时就生效,关闭则失效),全局变量(只要不是局部变量和内置变量,那么就是全局变量,文件级名字,在脚本文件执行期间被删除或者结束后失效),局部变量(函数里定义的变量,函数调用时生效,关闭时失效)。
函数内要使用全局变量时,在变量面前加一个global。函数要使用其内定义函数里定义的变量则需在变量面前加nonlocal
内置变量和全局变量都是全局作用域,任何位置都可以访问,改范围的民资会伴随程序的整个生命周期。而局部变量值有局部作用域,只能在函数内使用,调用函数时生效,结束调用则失效。
三种名称空间的加载顺序及查找顺序
函数对象在python中是第一类对象可以先intstr一样使用。
字符串为函数名后面加()就成了函数list1[0]()

可以直接变量引用:

def bar():
	print("i am bar function")
f=bar
f()

可以当做参数传递:

def bar():
	print(" from bar")
def wrapper(func):
	func
wrapper(bar)

可以当做函数的返回值:

def foo(func):
	return func
f=foo(bar)
f()

可以当做容器类型的元素:

list1=[bar,foo,wrapper]
list1[0]()
函数对象的应用

一个功能定义一个函数,根据返回的不同参数阿里来选择不同的功能函数。工程中函数的使用

闭包函数

闭包函数:定义在函数内部的函数,即函数的嵌套定义。闭包函数(函数里的定义的函数)的作用域在函数定义阶段就固定死了,与调用的位置无关。内部的无传递的值已固定。
闭包函数的用法就是给外层函数传参时,此外层函数其内部的闭包函数不用传参都可以使用到外层函数的参数。
在这里插入图片描述

装饰器
装饰器说明

器就是工具(工具既是函数),装饰器指为被装饰的对象添加新功能。
项目一上线之后要遵循开放封闭原则。对要修改的函数对象内的源代码和调用是封闭的,对功能扩展是开放的。装饰器就是遵循这个原则的解决方案,能够在不修改源代码的前提下为函数添加新的功能。应用场景:为多个功能函数添加统计时间功能,或为每个页面功能添加用户登录验证功能。

无参装饰器

新添加的功能即装饰本身没有参数,装饰器函数就是在源代码不可变的函数用来两层外层函数来包裹。

#装饰器
import time

#装饰器也是一个函数,使用之前要先定义,所以使用语法糖时,装饰器要放在最上面
def timer(func):#装饰器功能命名
    #使用闭包函数,使其能够返回闭包函数(装饰器功能函数)
    #如不使用闭包函数,就会改变func()的调用模式,是由inner来调用,不能赋值inner()给变量
    def wrapper(*args,**kwargs):
        '''
        新添加的功能,装饰器逻辑
        '''
        start_time=time.time()
        res=func(*args,**kwargs)
        stop_time=time.time()
        print(stop_time-stop_time)
        return res #解决原函数返回值无效问题
    return wrapper #返回闭包函数

@timer #语法堂相当于执行index=timer(index)
def index():
    time.sleep(1)
    print("welcome to index page")
    return 1

@timer #语法堂相当于执行home=timer(home)
def home(name):
    time.sleep(1)
    print('welcome to %s home page'%name)

home('lhj')
index()

index=timer(index)
home=timer(home)

home('lhj')
index()

运行结果,语法糖,装饰器可以嵌套使用

在这里插入图片描述

有参装饰器

在一些项目中不同数据可能会存放在不同的数据库中,所以需要根据参数来判断使用的数据库,再外面再加多一层函数用于接收全局参数,使用语法糖时则要传入参数。有参装饰器使用
装饰器使用的是闭包函数的原理,返回的是和原函数同名字的函数地址,加上()就可以调用这个函数,所以给我们的感觉就是原来的函数没有变化,却添加了新功能。

第八章 迭代生成

迭代器

迭代器即迭代的工具,迭代就是每次重复的结果都基于上一次的结果,就是有记录。
list,dict,file等是python自带的可迭代对象拥有iter()方法(返回值是迭代器对象,for循环中就是用这个方法获取in后面可迭代对象的迭代器对象,然后使用迭代器对象中的next方法迭代取值)
迭代器对象有next()方法可以取下一个迭代器对象中的一个值。迭代器的优点是节省内存空间,可以从没有索引的数据类型set,dict中单独去一个值。缺点是取值只能一个一个往后取,无法用len获取迭代器的长度。

生成器

生成器是人为制造的特殊迭代器。
yield关键字为我们提供了一种自定义迭代器的方式。代替函数中的return返回值,不同的是yield可以返回多个值,且保存了函数的执行状态,记录返回到第几个值。
函数内有yield关键字调用函数时不会执行函数体代码,而是返回一个生成器对象,需要通过iter转为迭代器对象,再通过next一个一个读取迭代器对象中的值。
生成器示例

yield表达式
yield有暂停函数的功能,可以用send给生成器函数里的yield传值。
应用场景:逐个喂食并记录吃过的食物。
yield表达式用法

面向过程编程思想

记录解决问题的步骤过程。以上的示例都是面向过程的思想。
优点:复杂问题流程简单化
缺点:修改一个阶段会牵一发而动全身,扩展性差。

合并表达

三元表达式

三元表达式仅适用于:条件成立返回一个值,条件不成立返回另一个值(一个简单的if_else return)。res=x if x>y else y

函数递归调用

函数递归调用就是函数在调用过程中又直接(自身调用自身)或间接(自身调用中间函数调用自身)的调用了函数本身,是一种特殊的函数嵌套调用。
**递归用法:有明确的结束条件,进入下一个递归时问题的规模要减小,python中没有尾递归优化
递归的应用:递归也有循环效果,与while不同的是:while需要一个明确的循环条件而递归需要一个明确的结束分支。
**
递归会占用大量的内存使机器卡死,所以python有一个最大递归深度来保护机器。

#查看递归限制的最大层数
import sys
print(sys.getrecursionlimit())#原本为3000
sys.setrecursionlimit(3500) #设置为3500,上限受机器硬件性能限制
sys.getrecursionlimit()

示例
递归分两个阶段:回溯和递推,一定要满足某种条件结束回溯,否则无限递归。
第一个问题的答案依赖于下一个问题,但是必须有最后一个确切的回答来结束,不然就变成了无限递归。

递归示例

#递归
"""
同学说比后一个说的大两岁,到最后一个说自己是18岁。
n代表有几个同学回答,但n为1时既是最后一个同学回答,
为结束条件,不可再有不确定的返回值。
"""
def get_age(n):
    if n==1:
        return 18
    else:
        return get_age(n-1)+2
get_age(5)  #26
匿名函数

匿名函数:没有名字的函数。
匿名函数使用规则:冒号左边为参数,右边为返回值,不需要return
(冒号右边类似三元式)lambda: x,y : x if x>y else y
没有返回值的匿名函数赋值给变量是没有意义的

f=lambda  x:print(x)
res=f(3)  #打印x,无返回值为none
print(res) #none
f=lambda x:x+2 #定义函数未执行
print(f(2)) #执行返回x+2

内置函数max,min,sorted的原理都是for循环,用max比较字典数据类型时时比较字典里面的key,所以我们可以通过指定max里的key参数来指定比较的参数

dict_test={'a':1,'b':4,'c':3}
    '''
    max通过for循环来逐个读取dict_test里的值来比较,用匿名函数来定义比较键,
    x相当于从序列中迭代出来的k(字典的key)
    for k in dict_test:
        key=dict_test[key]
    '''
    print(max(dict_test,key=lambda x:dict_test[x]))

内置函数map,reduce,filter与匿名函数lambda的联用

#内置函数map,reduce,filter与lambda的联用
nums=[1,2,3,4,5]
'''map第一个参数是表达式,第二个是序列,此map的功能是
传入序列的每个元素是对序列的每个元素平方,返回一个迭代器
'''
res=map(lambda x:x**2,nums)
#用list根据for循环原理将迭代器转为列表,for i in res: list.append(i)
print(list(res))

map与lambda联用示例
reduce是一个函数操作工具库functools里的一个方法,其功能则是合并数字,字符串
reduce(函数,可迭代对象,初始值)
应用场景:计算1+2+…+100的和。

res=reduce(lambda x,y:x+y,range(1,101),0) 
'''
初始值0赋值给x,相加后函数返回的值再作为初始值给x,
然后从range(1,101)可迭代对象里去出下一个值2给y。
既是y的值是从可迭代对象里取的,而x的值是一个动态变化的初始值(由自定值和函数返回值决定)
'''

filter(过滤函数):
filter只能过滤真假留下为 True的值

age=[21,12,22,11,13,15,3,2,1]
res=filter(lambda x:x>10,age)
#返回是True的元素
print(list(res))
列表生成式

列表生成式既是生成列表的表达式。
列表生成式构建列表比普通的空列表append更快是因为一个个放和多个一起放的区别,节约对内存的读写,使用列表表达式要注意尽量一个只写一组forif来保证简洁性。
提升硬件性能远比从软件上深层优化容易得多,提升硬件性能的花费一定比工程师时间上的花费所兑换的金钱要少。

list1=['part%s'%i for i in range(100)] # 生成100个列表部分
生成器表达式

当列表很大时,用列表表达式会占用大量的内存卡机器。
所以这时候只要将生成的对象改为生成器(把[]改成())就可以迭代取值,不会一下子生成一个巨型列表。
bulder=(‘part%s’%i for i in range(10000000000))

第十章 模块对象

模块是一系列功能的集合体,模块也是一个对象。当功能太多时,需要为多个功能分组成各个模块。
但作为可执行文件(脚本文件)被执行时,则__name__会变成__main__,如果以模块文件是被import调用时则变成模块的名字。因此我们会把测试代码放到if __name__ == '__main__':l里执行。
import model.py导入模块的过程:
创建一个模块的名称空间a(变量名引用变量地址),执行模块对应的文件model.py,将产生的名字存放于模块文件model.py所对应的的名称空间a,在当前执行文件main.py中拿到一个模块名model,该模块名model指向模块文件所对应的名称空间a
模块中的功能执行始终以模块自己的名称空间为主。

from module_name import *和import module_name的区别在于使用时前者不用加模块名,而后者要加。
模块查找路径:内存中已加载的模块 -> 内置模块 -> sys.path路径(脚本工作路径)中包含的模块
项目中尽量用相对路径(相对于项目根目录)。可以使用sys.path.append('..')来添加路径但是不推荐。

为包的文件夹中有个初始化文件__init__.py(在包创建时执行,将产生的包名字(引用)存放于包的名称空间中),包 包含 模块,模块 包含 功能。

常用模块

time模块:规定时间形式,打印进度条
datatime:转数据格式,计算日期差
shutil与tarfile:压缩与解压文件
logging:日志管理操作
json与pickle:序列化与反序列化
os:判断文件/文件夹是否存在即文件大小
sys:获取文件夹路径及相关文件管理操作
shelve,re,hashlib(哈希算法-输入内容得到一串不可逆推内容的定长hash值),subprocess(在程序中执行系统命令,如window下的cmd)

第十一章 类与对象

类的三个要素(类名,基类,类体代码)
面向过程:简单化复杂问题,却不利于修改和扩展。适用于编写操作系统,git,apache等软件。
面向对象:应用软件不断变化需求,用扩展性好的面向对象方法来开发更适合。
类名一般是用名称或名词词组,变量表示特征,函数表示技能。
类在定义了之后会立刻执行类里面的代码,类里的函数还是自定义。
查看类可通过类名.__dict__()来查看,返回的是一个字典,变量/方法名字:内存地址。
self位置参数指的是类实例后对象的本身。
类中的__xxx__()方法一般是自动执行的。

第十二章 名称空间

__init__()里定义的变量名称存放在对象名称空间,但变量在对象名称空间找不到时才会到类的名称空间(在有self参数的外面定义的变量名称存在于类名称空间中,这个变量是类变量,所有类对象用同一个,是一个全局变量)里找。
对象名称空间与类名称空间是完全分开的,空间之间没有包含关系。
绑定方法就是绑定给哪个对象用的方法,需要传入对象本身self。而类方法与类变量是供所有对象共同使用的。
如果要在类里定义类方法或静态方法,则在其方法名上方加上装饰器语法糖@classmethon、@staticmethod,静态方法也叫普通方法,非绑定方法。

类与类型是一个概念
str,int,list,tuple,set…都是在调用类,实例化对象

第十三章 三大特性

继承

通过继承可以避免代码的冗余,优化代码
python中有单继承和多继,可以通过xx.__base__的来查看他的父类基础,返回一个父类们的元组。
子类中没有init函数时会使用父类的init函数,属性查找也是,先在自己的绑定方法中找,再去类找再去父类,爷爷类中找。

经典类和新式类

python2中有经典类(前类-父类或爷爷祖宗类没有继承object)和新式类之分,python3中则全都为新式类(前类继承了object类)。
两种类在多继承状态下查找属性方法的区别:
当类是经典类时,多继承状态下,在自身查找不到属性方法时会按照深度优先(找到最深才停止)的方式查找上去。
当类是新式类时,多继承状态下,在自身查找不到属性方法时会按照广度优先(试探迂回,进几步还不到终点,退回来往宽度即左右查)的方式查找上去。在新式类中提供了一个属性查找方法mro(),返回查找类的顺序列表。
super()是根据当前对象的mro列表来继承查找
super继承查找

派生,在继承的基础上有自己的新东西先用自己的,即重写。重写init函数等,但父类代码还要用到时有如下两种方式引用父类代码:

派生/重写方法直接覆盖会存在代码冗余重复
指名道姓的调用,指明调用哪个类的初始化方法,而这个类可以不是父类,不会自动传self值所以都要手动传self值
super()的返回值是一个专门用来调用父类属性方法的特殊对象
python3中的super不用自己写self,但继承多个类时要指定super是哪个类如super(类名)
组合和继承都是解决代码冗余的方案。继承描述的是类与类之间的从属关系,组合描述的是类与类之间的交叉关系(一个类产生的对象拥有一个属性,而属性值来自于另一个类的对象)。
如给学生和老师的出身日期赋值,分别实例一个日期时间对象来赋值。
继承是强耦合,而组合是解耦合,所以在工程中从软件的扩展性来看组合的解耦性更有利。在经典源码中会大量使用组合与继承。

封装

封装既是封上口,不让内部属性方法给别人调用。封装是为了控制权限和隔离复杂度分好内外。
__xx/__xx()封装隐藏起来,外部无法调用访问,除非用_类名__属性名(__就是在类定义时把名字变成_类名__属性名
property伪装:把一个函数属性伪装成一个变量属性,如人的BMI指数是根据输入人体信息动态变化的,要写一个函数来计算,但是BMI是一个变量,调用的却是函数方法要加(),不符合开发规范,所以只要在返回BMI值的函数上加个@property装饰器就可以将函数伪装成变量,就不用加()。
property伪装函数成变量
property伪装函数的修改及删除
说明

多态

一种事物拥有多种形态,即从属关系的继承。不用考虑对象的具体种类,直接使用父类拥有的能力,派生则是使用具体种类的功能。
项目中可以写好接口定义类名让别人实现,用metaclass=abc.ABCMeta
在这里插入图片描述

第十四章 类的宿主

反射内置函数

反射内置函数:hasattr,getattr,setattr,delattr通过这些字符串来操作类和对象的属性,(根据名称字符串和类来获取属性,平时都是指定类名属性来找)
linux系统中的输入命令行就是用到这个反射内置函数,通过输入字符串(属性名称)来调用类中的方法。
cmd命令过程
在这里插入图片描述

面向对象内置函数

__call__调用对象的时候自动执行。
str 打印时自动执行,前后有__函数一般为自动执行的。。
__del__对象被删除时自动执行。(python只能回收应用程序资源,即我们编写的代码变量,而系统资源(file打开,数据库连接等)是无法在程序运行结束之后自动回收的),需要我们手动close()可以加到__del__中
__dict__类的静态函数、类函数、普通函数、全局变量以及一些内置的属性都是放在类__dict__里的,对象的__dict__中存储了一些self.xxx的一些东西。

元类

exec(字符串代码,全局名称空间,局部名称空间)可以用来执行字符串类的代码
exec函数示例
元类(一切皆对象)
(元类)type是类的类,所以类也是对象,
类的三个要素(类名,基类,类体代码)
元类type定义类的过程
type(类名-数据类型字符串,基类-object,类的名称空间-各种属性方法位置)中的参数与类的三要素一一对应。
type的内部用exec来执行类的三要素就达到了定义类的效果

单例模式:

第十五章 异常处理

程序发生错误就会产生异常
异常的构成(异常追踪信息,异常类型,异常值)
异常的构成
语法异常:语法异常
逻辑异常:死循环
索引异常:在这里插入图片描述
键值对异常:在这里插入图片描述
属性异常:在这里插入图片描述
常用异常总结:
在这里插入图片描述
异常捕捉的使用如下:
在这里插入图片描述
try else使用,else会在except没运行时运行及程序正常结束时。

raise主动触发异常
在这里插入图片描述
assert断言
assert断言语句用来声明某个条件是真的,其作用是测试一个条件(condition)是否成立,如果不成立,则抛出异常。
在这里插入图片描述
自定义异常
在这里插入图片描述

第十六章 七层协议

推荐书籍:tcp-ip协议
两种架构:C/S:客户端-服务端(打印机,qq,微信等应用软件);B/S:浏览器-服务端(各种网站系统),严格来讲也是C/S架构中的一种。
服务端肯定是在公司的服务器上运行的,消息的传递是先由客户端请求到服务端再发送到另一个客户端(可以是原来那个也可以是另一个)的。
网络编程的实质就是编写一个客户端和服务端实现基于网络的通信。
计算机之间通过物理连接介质(通信载体)根据互联网协议标准(统一的语言才能通信)来通信。
在这里插入图片描述
在这里插入图片描述

物理层:
发送端网卡(发送帧)-网线/无线电波(0/1高低电平)-交换机/路由器/防火墙等等-网线/无线电波(0/1高低电平)-接收端网

数据链路层:
在物理层的上一层,负责将二进制数据进行分组打包成帧或将帧重新组合成数据。具体操作如下:
二进制数据分组统一用以太网协议(数据分组协议),协议内容如下:
一组电信号构成一个数据报叫做帧。每一帧分报头(head)和数据(data)两部分。

在这里插入图片描述
每个网卡都有一个全球唯一 的mac地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值