Python核心开发
一.包和模块
1. 包和模块的定义
为了更加有好的对python代码进行管理,出现了包和模块的概念,包和模块的出现主要是为了将代码按照不同的功能进行整合,以达到大幅度提高代码的可读性及代码质量,方便项目中的协同开发
Python中的包和模块,首先是按照代码的功能进行整理,将相似的代码整合到一起便于统一管理。在python中,每一个文件都是一个模块,在每一个python文件中,封装类似的功能的变量、函数、类型等。在python中,当一个文件夹包含多个python模块,并且该文件夹中有一个init.py的特殊声明文件,那么这个文件夹就是一个包,它可以将大量功能相关的python模块包含起来进行统一管理。包和模块都可以被其他模块通过import关键字进行引入使用封装的模块和代码,提高代码的复用性,避免大量重复代码的出现。
2. 包和模块的复用
在python中,将包和模块打包通过import关键字供其他模块引入和使用主要是为了提高代码的复用性。包和模块的引入通常有两个关键语法,import和from...import。Import方式可以引入包和模块, import引入的包和模块会自动从当前文件夹中、系统环境变量PYTHONPYTH中,以及系统的sys.path路径中查询是否存在该名称的包和模块,如果存在,就可以进行引入调用了,若不存在,则会报错。
from...import语法方式主要是针对出现了包结构的python代码而特定的代码引入方式,首先要非常明确代码的组织结构才能正确使用from...import语法方式的引入和复用,from...import语法分为两种操作,其一为使用./..的相对路径的引入操作方式,相对引入本身是相对正在操作的文件的路径,相对路径是依赖于它们所属的父路径;其二则是直接使用包或者模块名称的绝对引入方式,绝对引入操作方式比较直接,它是从最外层的包的源头直接开始操作的。
3. 再说模块和包
模块:
1)在一个python模块中可以包含的数据有变量、函数和类型等,是一个完整独立的代码块
2)独立模块中的变量分为全局变量和局部变量,全局变量是整个模块的变量,可以被其他模块引入使用;局部变量是当前模块中某个函数或类型的变量,只能被当前的函数及类型使用
3)模块被其他模块引入后,相当于在当前模块重写了被引入模块的代码,所以会执行被引入模块中的所有代码
4)模块中的测试代码可以包含在if name == “main”: 这样的语句中,在这些语句中的模块不会在引入其他模块时执行
5)一个标准模块的定义方式分为以下几个步骤
coding:utf-8
(# 引入系统标准模块
(# 引入第三方模块
(# 引入自定义模块
(# 声明定义变量
(# 声明定义函数
(# 声明定义类型
(# 当前模块测试代码
包:python中的标准包,是包含一个init.py声明文件的文件夹,在包中,可以创建多个模块,由包进行统一的路径方式和导入方式管理。在默认情况下,包都是可以直接导入的,同样为了方便,我们也可以通过通配符的方式来一次引入包中所有的指定模块。all属性就是用于模糊导入的特殊魔法属性,值是一个包含模块名称的列表,主要声明在init.py文件中,用于定义可以使用通配符的方式引入的模块。
4. 再说导入
import及 from...import导入的基本语法结构分别如下:
(# 导入一个包/模块 :
Import 包名称/模块名称
from 包名称 import *
(# 导入一个包中的某个模块 :
import 包名称.模块名称
from 包名称 import 模块名称
(# 导入一个包中某个模块的某个函数 :
Import 包名称.模块名称.函数名称
from 包名称.模块名称 import 函数名称
(# 导入一个人包中某个模块的某个类型【使用别名】:
Import 包名称.模块名称.类型名称 as 别名
from 包名称.模块名称 import 类型名称 as 别名
5. 自定义包的发布
已经开发好的模块包如果想要发布出来供给其他人使用使其可以通过命令直接安装使用的话,可以进行打包发布,自定义包的发布分为两种,本地发布和网络发布。
本地发布:在已经开发好的包文件夹下新创建一个python模块:setup.py。模块中需要引用构建包信息的模块 from distutils.core import setup。定义发布包文件的信息格式如下:setup(name = “xxx”)模块中的其他内容格式同上,可自行添加内容,暂不过多说明。执行完当前程序包文件的构建操作命令后,需按照标准格式组织包中的所有数据文件。
构建操作命令格式如下:
python setup.py bulid
REMARK:构建完的文件
可以通过python setup.py install 命令直接当成第三方模块进行安装
执行命令进行包的打包发布格式如下:
python setup.py sdist
REMARK:打包的文件,主要方便进行网络传输,打包之后会在dist中创建包含包中所有信息的tar.gz压缩包文件,该文件可以通过git等方式提交给对应的开源组织发布你的自定义包模块
网络发布:首先,需要进入<u>http://pypi.python.org/pypi</u>网站上注册一个自己的账号,这个网站是目前大部分python第三方模块集中的一个管理社区平台;其次,准备好自己的python程序包,并在包中准备好了setup.py 文件。在setup.py中,定义好如下的程序包的描述信息:
xxx_users/
init.py
moduels.py
manager.py
menus.py
setup.py
之后执行打包命令:python setup.py sdist
接下来,安装第三方模块twine,方便上传我们打包的项目文件:pip install twine,之后上传项目:twine upload dist/*
6. 关于Main 主方法
Python中的最小运行单元数代码块,在代码块中,哪怕只有一行代码也能执行,所以没有主方法或函数的概念,但是主方法在python中是有必要存在的,主方法的使用,可以避免在执行代码的过程中由于测试代码的一并执行而引起的不必要的错误和系统资源的浪费。虽然python中没有主方法主函数的概念,但我们可以通过模拟主函数的方法去达到我们想要的结果。Python中的模块有一个魔法属性name.表示当前模块的运行时的名称,它具有以下特性:
1)当前模块如果是程序运行入口,name 的值:main
2)当前模块如果被其他模块import引入 name的值:模块名称
所以我们可以定义模块demo.py,main.py,用于测试魔法属性的操作,利用main 的特性完成main方法的设计
二.内存分析和处理
1. 程序内存浅析
程序的运行离不开对内存的操作,一个软件要运行,需要将数据加载到内存中,通过CPU进行内存数据的读写完成数据的运算。软件程序在计算机中的执行,主要是通过数据单元、控制单元、执行单元共同协作,完成数据的交互,达到程序处理数据的目的。Python程序在运行过程中,主要是解释器从系统中申请内存空间以运行python软件解释器将申请的内存主要区分为四个部分用于处理执行的程序软件,分别是:
1)栈内存区:用于直接分配数据,存取速度较快、数据存储不稳定、适用于小数据块的快速存取,一般在程序中用于存储变量数据
2)方法区:主要用于加载程序中使用的代码数据、二进制数据、方法数据等等程序运行需要的预加载数据
3)静态区:主要用于加载存储程序中的一些静态数据、常量数据等等,在python中的不可变数据类型的数据,也会存储在静态常量区中
4)堆内存区:存储数据持久稳定,一般用于存储加载较为重量级的数据,如程序运行过程中的对象都是存在堆内存区中的。
在python中,根据数据是否可以进行修改提供了两种不同的数据类型,分别是:
1)不可变数据类型:一般基本数据类型都是不可变数据类型
2)可变数据类型:一般组合数据类型和自定义数据类型都是可变数据类型
3)区别:可变数据类型是在定义了数据之后修改变量的数据,内存地址不会改变;不可变数据类型在定义了数据之后修改变量的数据,变量不会修改原来的内存地址而是会指向新的地址,原有的数据进行保留
Python中最小的运行单元是代码块,代码块的最小单元是一行代码,在实际开发过程中,需要注意python的两种操作方式
1)交互模式:在交互模式下,每行命令都是一个独立的代码块,每个代码块运行会独立的申请一次内存,在操作过程中交互模式没有推出的情况下遵循python官方操作标准
2)IDE开发模式:在IDE开发模式下,代码封装在模块中,用过python命令运行模块时,模块整体作为一个代码块向系统空间申请内存并执行程序,执行过程中对于基本数据类型进行缓存优化操作
2. 操作符号的使用
在python中,可以通过操作符号判断对象和对象之间的关系与值的情况,进行组合数据类型及不可变数据类型的数据判断:
1)is : 判断多个对象是否存在于同一个内存地址,是否同一对象
2)== : 判断多个对象中的内容是否一致
3. 引用、浅拷贝、深拷贝
对象和对象之间,通过内存的操作存在各种各样的关系。对象的创建,依赖于申请内存空间中加载的数据,对象在内存的创建过程依赖于三部分内存处理:对象内存分配地址、引用变量分配内存地址、对象和引用变量之间的关联。当程序中要在多个地方使用一个对象数据时,有三种不同的操作方式:
1)如果程序中多个不同的地方都要使用同一个对象,通过对象的引用赋值,将同一个对象赋值给多个变量
2)如果程序中多个不同地方都要使用相同的对象数据,通过对象的拷贝完成数据的简单复制,对象中包含的数据要求必须统一
3)如果程序中多个不同的地方使用相同的且独立的数据对象,通过对象的深层次复制将对象的数据完整复制成独立的另一份
对象的引用赋值,可以将对象的内部地址同时赋值给多个变量,这些变量中存放的都是同一个引用地址,如果通过一个变量修改了对象内容,其他变量指向的对象内容也会同时发生改变。Python中对象的引用赋值,针对的是可变类型,不适合不可变类型,不可变类型的引用赋值操作有只读不写的特征,一旦通过变量重新赋值就会重新指向新的引用对象
对象的浅拷贝,是一种对象的临时备份,核心机制主要是赋值对象内部数据的引用;对象的深拷贝,是对象数据的直接拷贝
4. 垃圾回收机制
垃圾回收机制基本是所有高级语言的标准配置之一,在一定程度上,能优化编程语言的数据处理效率和提高编程软件开发软件的安全性能。Python中的垃圾回收机制主要是以引用基数为主要手段,以标记清除和分代回收为辅助操作手段完成对内存中无效数据的自动操作管理
引用计数是python中垃圾回收机制的核心操作算法,当一个对象被创建或者拷贝时,引用计数就会加一,这个对象的多个引用计数变量被销毁时引用计数就会减一,为零时,就会被清除。它的优点是操作简单,实时性能优秀,能在最短的时间内获得并运算引用数,缺点是必须提供对等的内存消耗来维护引用计数,无形中增加内部负担。同时对于循环应用及对象之间的相互引用,无法进行计数操作,会造成内存常驻的情况。
标记清除算法的核心思想是,首先找到python中的一批根节点对象,通过根节点独象找到它们的子节点对象,如果对象可达,将可达部分的对象在程序中保留,如果不可达,则清除。
分代回收机制,是一种通过空间换取时间效率的做法,python内部处理机制定义了三个不同的链表数据结构,第零代、第一代、第二代,并且对这三代都进行了阀值限定,当第零代的阀值达到临界点时,对第零代对象进行引用计数运算,将没有引用的对象回收,将有引用继续指向的对象移动到第一代中,同理,阀值到达特定的数值时,对第一代、第二代进行相同处理。
Python中的gc模块提供了垃圾回收处理的各项功能机制,必须调用gc模块才能使用,在程序开发过程中需要注意:
1)项目代码中尽量避免循环使用
2)引入gc模块,启用gc模块自动清理循环引用对象的机制
3)将需要长期使用的对象集中管理,减少gc资源消耗
4)Gc模块处理不了重写del方法导致的循环引用,如果一定要添加该方法,需要显式调用gc模块的garbage对象的del方法进行处理
三.再说列表
1. 列表和列表的内存处理
列表是python组合数据类型中使用较多的类型之一,在程序开发过程中,对列表的操作有两种不同的情况需要考虑:
1)如何定义一个存放了大量有规律的数据的列表
2)列表中存储的数据量过大是否会对内存产生影响
Python中提供了对于有规律数据的快捷操作:推导式,通过推导式可以方便快捷的生成需要的数据。推导式分为简单推导式、运算推导、条件推导式、组合推导式。推导式的出现,极大程度的简化了存放有规律的数据列表的操作,在实际开发过程中,甚至可以基本代替一些简单程序结构实现一行代码独立功能流程
列表简介方便的操作性虽然给程序开发带来了非常便捷的操作效率,但列表本身存储数据的机制在进行大量数据的处理时,会极度的消耗系统内存。针对操作频繁的列表,列表生成器的油然而生。生成器的语法结构和推导式的语法结构及其类似,生成器对象必须通过系统内建标准函数来获取生成下一个数据,生成器的优异性能在于使用的时候才会运行下一个数据,而不会一次性将数据加载
2. 循环遍历与迭代器
Python程序中通过for循环进行循环遍历操作的,就是迭代器对象iterable,在自定义类型中,可以通过重写iter()方法,让自定义对象返回一个迭代器对象
四.再说函数
1. 函数的引用赋值和参数操作
Python中的函数,本身也是一个对象,常规定义语法的函数,就是将一个函数对象的引用地址赋值给函数名称的变量,通过函数名称的变量调用执行函数。如果函数就是对象,函数也可以和对象一样被引用赋值,也可以被当成参数传递给其他函数执行
2. 偏函数
偏函数可以让函数的操作执行更加人性化的处理,使用偏函数可以有效的“冻结”那些预先确定的函数,来缓存函数参数然后在运行时,当获得需要的剩余参数时,可以将其解冻传递到最终的参数中,从而使用最终确定的所有参数去调用函数。在一定程度上,偏函数只是一个语法糖,因为python中对于函数参数的处理已经有默认值的操作,完全可以替代偏函数的复杂操作
3. 装饰器函数
装饰器函数的本质是为其他函数添加附加功能,装饰器的返回值也是一个函数对象,原则:
1)不能修改被装饰函数的源代码
2)不能修改被装饰函数的调用方式
4. 闭包函数
在python中,函数执行结束时其中的数据就会丢失,在函数外部就不能访问函数中的数据。当需要函数外部直接操作函数中的数据时,可以将函数中的数据直接通过返回值返回,但是返回值的操作方式比较单一,能作为简单数据的处理方式。更加灵活的操作方式是闭包函数。闭包函数就是在函数中声明另一个函数
5. 匿名函数
很多函数中都存在匿名函数,匿名函数又名lambda表达式,它的主要作用是简化函数操作,将简单的逻辑封装在一个表达式中,从而省去定义函数繁杂的操作方式,主要起到简单处理函数的功能。匿名函数只能有一个表达式,返回值就是该表达式的结果。因为匿名函数没有名字,因此不用担心函数名冲突,它也是一个函数对象,可以将其赋值给一个变量,再利用变量来调用该函数,同样,匿名函数也可以作为返回值返回
五.标准模块和内建函数
系统标准模块:Python标准库中提供了大量的模块,通过dir()命令可以查看所有内建模块
系统内建函数:系统内建函数包含大量的操作处理
六.元类
类:元类是用来定义和构建类型的,在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段,在python中,类同样也是一个对象,可以赋值、拷贝、增加属性
类的动态创建:因为类也是对象,可以在运行时创建它们,使用class关键字即可。当使用class关键字时,python解释器自动创建这个对象
Type创建类、属性、方法:type还有一种完全不同的功能,动态的创建类。Type可以接受一个类的描述作为参数,然后返回一个类
元类:用来创建类
'
网友评论