PythonDay11
本节内容
- 单例
- new方法
- 异常
- 抛出异常
- 模块
- 包
- 发布模块
- pip
- 文件操作
- 文本编码格式
- eval函数
1.单例
单例设计模式
目的---让类创建的对象,在系统中只有唯一的一个实例;
每一次执行类名()返回的对象,内存地址是相同的;
2.__new__方法
使用类名()创建对象时,python的解释器首先会调用__new__方法为对象分配空间;
__new__是一个由object基类提供的内置的静态方法,主要作用有两个:
在内存中为对象分配空间;返回对象的引用
Python的解释器获得对象的引用后,将引用作为第一个参数,传递给__init__方法;
重写__new__方法一定要return super().__new__(cls),否则Python解释器得不到分配空间的对象引用,就不会调用对象的初始化方法;
class MusicPlayer(object):
def __new__(cls, *args, **kwargs):
print("创建对象分配空间")
return super().__new__(cls)
def __init__(self):
print("播放器初始化")
player=MusicPlayer()
print(player)
Python中的单例
class MusicPlayer(object):
#记录第一个被创建对象的引用
instance=None
def __new__(cls, *args, **kwargs):
#判断类属性是否空对象
if cls.instance is None:
#调用父类方法,为第一个对象分配空间
cls.instance=super().__new__(cls)
#返回类属性保存的对象引用
return cls.instance
player1=MusicPlayer()
print(player1)
player2=MusicPlayer()
print(player2)
初始化动作只被执行一次
class MusicPlayer(object):
#记录第一个被创建对象的引用
instance=None
#记录是否执行初始化动作
init_flag=False
def __new__(cls, *args, **kwargs):
#判断类属性是否空对象
if cls.instance is None:
#调用父类方法,为第一个对象分配空间
cls.instance=super().__new__(cls)
#返回类属性保存的对象引用
return cls.instance
def __init__(self):
#判断是否执行初始化动作
if MusicPlayer.init_flag:
return
#如果没有执行过,在执行初始化动作
print("初始化")
#修改类属性标记
MusicPlayer.init_flag=True
player1=MusicPlayer()
print(player1)
player2=MusicPlayer()
print(player2)
3.异常
程序在运行时,如果Python解释器遇到一个错误,会停止程序的执行,并且提示一些错误信息,这就是异常;
程序停止执行并且提示错误信息这个动作,我们通常称为:抛出异常;
程序开发时,很难将所有的特殊情况都处理的面面俱到,通过异常捕获可以针对突发事件做集中处理,从而保证程序的稳定性和健壮性;
捕获异常
在程序开发中,如果对某些代码的执行不能确定是否正确,可以增加try(尝试)来捕获异常;
try:
尝试执行的代码
except:
出现错误的处理
try尝试,下方编写要尝试的代码,不确定是否能够正常执行的代码;
except如果不是,下方编写尝试失败的代码;
try:
#不能确定正确执行的代码
num=int(input("请输入整数:"))
except:
#错误的处理代码
print("请输入正确的整数")
print("-"*50)
错误类型捕获
try:
num=int(input("输入一个整数:"))
result=8/num
print(result)
except ZeroDivisionError:
print("除0错误")
except ValueError:
print("请输入整数")
捕获未知错误
except Exception as result:
print("未知错误%s"%result)
try:
num = int(input("输入一个整数:"))
result = 8 / num
print(result)
except ValueError:
print("请输入整数")
except Exception as result:
print("未知错误%s"%result)
异常捕获完整语法
try:
#尝试执行的代码
pass
except 错误类型:
pass
except Exception as result:
print(result)
else:
#没有异常才会执行的代码
pass
finally:
#无论是否异常,都会执行的代码
print("无论是否异常,都会执行的代码")
异常的传递
异常的传递--当函数/方法执行出现异常,会将异常传递给函数/方法的调用一方;
如果传递到主程序,仍然没有异常处理,程序才会被终止;
def demo1():
return int(input("输入整数:"))
def demo2():
return demo1()
#利用异常的传递性,在主程序捕获异常
try:
print(demo2())
except Exception as result:
print("未知错误%s"%result)
4.抛出异常
抛出异常:1.创建一个Exception的对象;2.使用raise关键字抛出异常对象;
def input_password():
#提示用户输入密码
pwd=input("请输入密码:")
#判断密码长度
if len(pwd)>=8:
return pwd
#密码长度小于8主动异常抛出
print("抛出异常")
#创建异常对象
ex=Exception("密码长度不够")
#主动抛出异常
raise ex
try:
print(input_password())
except Exception as result:
print(result)
5.模块
在模块中定义的全局变量、函数、类都是提供给外界直接使用的工具;
模块就好比是工具包,要想使用这个工具包中的工具,就需要先导入这个模块;
模块的导入方式
import 模块1
import 模块2
通过模块名.使用模块提供的工具--全局变量、函数、类
如果模块的名字太长,可以使用as指定模块的名称,以方便在代码中的使用
import 模块名1 as 模块别名
注意:模块别名应该符合大驼峰命名法(DogModule)
#从模块导入某一个工具
from 模块名1 import 工具名
导入后,不需要通过模块名. 可以直接使用模块提供的工具--全局变量、函数、类;
如果两个模块,存在同名的函数,那么后导入的模块函数,会覆盖掉先导入的函数;可以通过起别名解决;
#从模块导入所有工具
from 模块名1 import *
这种方式不推荐使用,因为函数重名并没有任何提示,出现问题不好排查;
原则--每一个文件都应该是可以被导入的
一个独立的Python文件就是一个模块;在导入文件时,文件中所有没有任何缩进的代码都会被执行一遍;
__name__属性可以做到,测试模块的代码只在测试情况下被运行,而在被导入时不会被执行;
def main():
pass
if __name__=="__main__":
#文件被导入时,能够直接执行的代码不需要被执行
main()
6.包
包是一个包含多个模块的特殊目录;目录下有一个特殊的文件__init__.py;包名的命名方式和变量名一致,小写字母+_;
使用import 包名可以一次性导入包中所有的模块;
__init__.py 要在外界使用包中的模块,需要在__init__.py中指定对外界提供的模块列表;
#从当前目录导入模块列表
from . import 模块1
from . import 模块2
7.发布模块
创建setup.py
from distutils.core import setup
setup(name="m_bao",#包名
version="1.0", #版本
description="发送和接收", #描述信息
long_description="完整的发送和接收",#完整描述信息
author="mm", #作者
author_email="mm@123.com",#作者邮箱
url="www.xxx.com",#主页
py_modules=["m_bao.send",
"m_bao.receive"])
构建模块
python3 setup.py build
生成发布压缩包
python3 setup.py sdist
安装模块
tar -zxvf m_bao-1.0.tar.gz
python3 setup.py install
卸载模块
直接从安装目录下,把安装模块的目录删除就可以;
8.pip安装第三方模块
第三方模块通常是指知名的第三方团队开发的并且被程序员广泛使用的Python包/模块;
pip是一个现代的,通用的Python包管理工具,提供对Python包的查找、下载、安装、卸载等功能;
#安装pygame到Python 3.x环境
sudo pip3 install pygame
sudo pip3 uninstall pygame
9.文件操作
文件:存储在某种长期存储设备上的一段数据...
文本文件:可以使用文本编辑软件查看,本质上还是二进制软件;
二进制文件:保存的内容不是给人直接阅读的,而是提供给其他软件使用的(图片文件、音频文件),不能使用文本编辑软件查看;
操作文件
- 打开文件
- 读、写文件 (读将文件内容读入内存,写将内容写入文件)
- 关闭文件
open函数的第一个参数是要打开的文件名(文件名区分大小写),如果文件存在,则返回文件操作对象;不存在,会抛出异常;
read方法可以一次性读入并返回文件的所有内容;
close方法负责关闭文件;
#打开文件
file=open("readme")
#读取文件
text=file.read()
print(text)
print("-"*50)
#关闭文件
file.close()
文件指针:标记从哪个位置开始读取数据,第一次打开文件时,通常文件指针会指向文件的开始位置;
当执行read方法后,文件指针会移动到读取内容的末尾;
打开文件的方式
open函数默认以只读方式打开文件,并且返回文件对象;
f=open("文件名","访问方式")
readline方法可以一次读取一行内容,方法执行后会把文件指针移动到下一行,准备再次读取;
文件/目录常用管理操作
想要实现对文件/目录管理操作,需要导入os模块;
文本文件的编码格式
ASCII编码:计算机中只有256个ASCII字符,一个ASCII在内存中占用1个字节的空间
UTF-8编码:计算机使用1-6个字符来表示一个UTF-8,大多数汉字使用3个字节来表示,UTF-8是UNICODE编码的一种编码格式;
Python 2.X 默认使用ASCII编码格式,Python 3.X默认使用UTF-8编码格式;
在2.X中可以在文件第一行增加以下代码,使用UTF-8
# *-* coding:utf8 *-*
或
# coding=utf8
即使在文件使用UTF-8的编码格式,但是在遍历字符串时,任然会以字节为单位遍历字符串;要能够正确遍历字符串,在定义字符串时,需要在字符串的引号前,增加一个小写字母u,告诉解释器这是一个unicode字符串;
eval()函数十分强大--将字符串当成有效的表达式来求值并返回计算结果;