续上上篇的讲解:【备战测开】—— 编程语言Python(一)
6 面向对象编程
所谓的面向对象其实就是把属性和方法封装起来,以供重复调用
6.1 类和对象
参考博客:python类和对象最全详解(持续修订中)
class Person:def __init__(self,name,age,sex):self.name = nameself.age = ageself.sex = sexdef sing(self):print(f"{self.name}唱的真好听")def dump(self):print(f"{self.name}跳的真不错")def rap(self):print(f"{self.name}世界第一")
shuaishuai = Person("帅帅",18,"superman")
对象:实际生活中具体的事物
类:封装对象的属性和行为的载体
总结:类是对象的抽象,对象是类的具体实例
__init__
:第一个参数必须是self,代表当前对象,然后第二个参数开始就随意,但是这些参数在创建对象的时候必须一一实现
命名空间:类空间和对象空间
类也遵从自上而上执行,所以如果类里面有同名的方法,前一个方法会被后一个方法覆盖
# 创建一个类,能够自动统计当前类创建了多少个对象
class Person():num = 0def __init__(self):Person.num += 1
print(Person.num)
Person()
Person()
Person()
Person()
print(Person.num)
常见的内置方法
常用的内置方法:
__init__:
1.用来构造初始化函数,用来给对象进行初始化属性,所以不需要返回值
2.创建对象的时候自动调用
3.自定义类如果不定义的话,默认调用父类object的,同理继承也是,子类若无,调用父类的,若有,调用自己的class Animal:def __init__(self):print("init初始化方法,没有调用父类object")Animal()
#结果:
init初始化方法,没有调用父类object__new__:
1.用所给类创建一个对象,并且返回这个对象
2.因为是给类创建实例,所以至少传一个参数cls,参数cls代表代表要实例化的类,此参数在实例化时用python解释器自动提供
3.在类实例化时内部创建类实例的函数,并且返回这个实例,所以它是实例时最先被调用的方法,一般不要人为定义该方法
4.因为要创建实例返回实例,所以要有返回值。return父类__new__出来的实例,或者直接是object的__new__出来的实例__class____delattr__
__dict__
__dir__
__doc__
__eq__
__format__
__ge__
__getattribute__
__gt__
__hash__
__init__
__init_subclass__
__le__
__lt__
__module__
__ne__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__sizeof__
__str__
__subclasshook__
__weakref__
类的成员主要有属性和方法,属性可以随意,方法的第一个参数必须是self
访问限制:可以使用单下划线,双下划线,首尾双下划线来限制访问权限
单下划线开头的是protected类型的成员,只允许类本身和子类进行访问,不能使用from xxx import ccc进行导入,双下划线只能由定义了该属性或方法的类调用,而不能由类的对象调用,类的对象如果想调用,必须使用set/get方法
class Person:def __init__(self, name,sex):self.name = nameself.__age = Noneself.sex = sexdef set(self,age):self.__age = agedef get(self):return self.__agedef sing(self):print(f"{self.name}唱的真好听")def dump(self):print(f"{self.name}跳的真不错")def rap(self):print(f"{self.name}世界第一")shuaishuai = Person("帅帅","superman") # 初始化
#这个时候初始化帅帅的年龄就会报错,可以使用set方法来赋值,get方法取值
shuaishuai.set(18)
print(shuaishuai.get())
属性
(1)创建用于计算的属性
python中使用@property
将一个方法转换为属性,从而实现用于计算的属性,将方法转换为属性后,可以直接通过方法名来访问,而不需要加括号,@property
可以将属性设置为只读属性
class Person:def __init__(self,name,age):self.name = nameself.age = age@propertydef func(self):if self.age < 150 and self.age > 0:print(self.age)else:print("想啥呢?")shuaishuai = Person("帅帅",18)
shuaishuai.func #func这个属性不能对其赋值,因为他本质也是一个函数
(2)为属性添加安全保护机制
python中有了私有属性和私有方法供大家使用。私有属性就是在属性前面加两个下划线,然后给这个私有属性给予set和get方法,这样对象调用的时候就只能通过set方法来进行赋值,get方法来获取值
class Person:def __init__(self, name, sex):self.name = nameself.__age = Noneself.sex = sexdef set(self, age):self.__age = agedef get(self):return self.__age
类与类之间的关系
有三种关系:
- 依赖(关联)
帅帅玩电脑,电脑需要帅帅玩
class Person:def run(self):print("我没事干")
class Computer:def play(self, tool):tool.run()print("我是电脑,玩我")
class Phone:def play(self,tool):tool.run()print("我有王者荣耀,来玩啊")
shuaishuai = Person()
dnf = Computer()
dnf.play(shuaishuai) #依赖是给一个类的对象的方法给另一个对象
wangzhe = Phone()
wangzhe.play(shuaishuai)
- 组合(聚合):一个类需要某个类的具体对象去做一些事情,这就是组合。轮胎和发动机组合成了车一样。
class Car:def __init__(self,name,power = None):self.__name = nameself.__power = powerdef set_power(self,power):self.__power = powerdef zhuang_Tread(self):print(f"{self.__name}装好了{self.__power.get_name()}的轮胎")def saiche_power(self):print(f"{self.__name}装好了{self.__power.get_name()}的发动机")class Tread:def __init__(self,name):self.__name = namedef set_name(self,name):self.__name = namedef get_name(self):return self.__nameclass Engine:def __init__(self,name):self.__name = namedef set_name(self,name):self.__name = namedef get_name(self):return self.__nametread = Tread("牛逼牌")
engine = Engine("赛车")
car = Car("奔驰",tread)
car.zhuang_Tread()
car.set_power(engine)
car.saiche_power()
- 继承(实现)
#固定结构:
#父类
class Person(object): #括号里面写要继承的类def __init__(self, name,sex):self.name = nameself.__age = Noneself.sex = sexdef set(self,age):self.__age = agedef get(self):return self.__agedef sing(self):print(f"{self.name}唱的真好听")def dump(self):print(f"{self.name}跳的真不错")def rap(self):print(f"{self.name}世界第一")#子类
class Boy(Person):passshuaishuai = Boy("帅帅","superman")
shuaishuai.sing()#结论:
可以看出,子类Boy什么都没有写,只是继承了一下父类Person,他就拥有了父类的属性和方法,但是私有属性没有被继承。
方法重写
class Person(object):def __init__(self, name):self.name = namedef sing(self):print(f"{self.name}唱的真好听")#子类
class Boy(Person):def sing(self):print(f"{self.name}最帅")shuaishuai = Boy("帅帅")
shuaishuai.sing()
#结果:帅帅最帅
这个时候我们可以发现,原来我们不重写sing方法的时候,他调用的是父类的sing方法,当我们在子类中进行重写之后,他显示的就是子类的方法。
由此可以得出查找顺序:对象调用某个属性或者方法的时候,会先在当前类中进行查找,如果找不到,就去他的父类对象今进行查找。
多继承和多重继承的区别
- 多继承是子类不断的继承父类,依次类推,最后的孙子类拥有父类跟子类的方法
#多继承
class Person(object):def run(self):print("人会跑")class Boy(Person):def like_girl(self):print("男孩喜欢女孩子")class Girl(Boy):def like_boy(self):print("女孩子也喜欢男孩子")class Kid(Girl):def kids(self):print("孩子是男孩跟女孩的爱情结晶")kid = Kid()
kid.run()
kid.like_girl()
kid.like_boy()
kid.kids()#结果
人会跑
男孩喜欢女孩子
女孩子也喜欢男孩子
孩子是男孩跟女孩的爱情结晶
- 多重继承:一个类可以从Python中的多个基类派生
class Base1:passclass Base2:passclass MultiDerived(Base1, Base2):pass
6.2 三大特性
6.2.1 封装
封装就是把一个个的属性和方法隐藏起来,只留下具体的接口供下一个人使用
私有属性:在属性前面加get/set方法,然后再当前类中进行调用和实现,外界只能使用这个属性的set/get方法来操作他。而且不能被子类继承
私有方法:在方法前面加两个下划线
破解私有属性:在名称前加上 _类名,即 _类名__名称(例如a._A__N)
其实加双下划线仅仅是一种变形操作
类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式
6.2.2 继承
#固定结构:
#父类
class Person(object): #括号里面写要继承的类def __init__(self, name,sex):self.name = nameself.__age = Noneself.sex = sexdef set(self,age):self.__age = agedef get(self):return self.__agedef sing(self):print(f"{self.name}唱的真好听")def dump(self):print(f"{self.name}跳的真不错")def rap(self):print(f"{self.name}世界第一")#子类
class Boy(Person):passshuaishuai = Boy("帅帅","superman")
shuaishuai.sing()#结论:
可以看出,子类Boy什么都没有写,只是继承了一下父类Person,他就拥有了父类的属性和方法,但是私有属性没有被继承。
方法重写
class Person(object):def __init__(self, name):self.name = namedef sing(self):print(f"{self.name}唱的真好听")#子类
class Boy(Person):def sing(self):print(f"{self.name}最帅")shuaishuai = Boy("帅帅")
shuaishuai.sing()
#结果:帅帅最帅
这个时候我们可以发现,原来我们不重写sing方法的时候,他调用的是父类的sing方法,当我们在子类中进行重写之后,他显示的就是子类的方法。
由此可以得出查找顺序:对象调用某个属性或者方法的时候,会先在当前类中进行查找,如果找不到,就去他的父类对象今进行查找。
多继承和多重继承的区别
- 多继承是子类不断的继承父类,依次类推,最后的孙子类拥有父类跟子类的方法
#多继承
class Person(object):def run(self):print("人会跑")class Boy(Person):def like_girl(self):print("男孩喜欢女孩子")class Girl(Boy):def like_boy(self):print("女孩子也喜欢男孩子")class Kid(Girl):def kids(self):print("孩子是男孩跟女孩的爱情结晶")kid = Kid()
kid.run()
kid.like_girl()
kid.like_boy()
kid.kids()#结果
人会跑
男孩喜欢女孩子
女孩子也喜欢男孩子
孩子是男孩跟女孩的爱情结晶
- 多重继承:一个类可以从Python中的多个基类派生
class Base1:passclass Base2:passclass MultiDerived(Base1, Base2):pass
6.2.3 多态
参考博客:python中对多态的理解
(1)多态
多态是指一类事物有多种形态,比如动物类,可以有猫,狗,猪等等。(一个抽象类有多个子类,因而多态的概念依赖于继承)
import abc
class Animal(metaclass=abc.ABCMeta): #同一类事物:动物@abc.abstractmethoddef talk(self):passclass Cat(Animal): #动物的形态之一:猫def talk(self):print('say miaomiao')class Dog(Animal): #动物的形态之二:狗def talk(self):print('say wangwang')class Pig(Animal): #动物的形态之三:猪def talk(self):print('say aoao')
(2)多态性
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
class Animal(object):def talk(self):pass
class Cat(Animal):def talk(self):print('miao miao')
class Dog(Animal):def talk(self):print('wang wang')
c = Cat()
d = Dog()def fun(obj):obj.talk()
fun(c)
fun(d)
多态性:一个接口,多种实现
好处:
(1)增加了程序的灵活性,以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(obj)
(2)增加了程序额可扩展性,通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(obj)去调用
6.3 运算符重载
参考博客:
浅析Python运算符重载
Python 运算符重载
6.4 装饰器
我们调用一个带有返回值的函数 x,此时函数 x 为我们返回一个函数 y,这个函数 y 就被称作闭包
def x(id):def y(name):print ('id:', id, 'name:', name)return yy = x('ityard')
y('程序之间')
闭包与类有一些相似:
(1)都能实现数据的封装、方法的复用
(2)通过使用闭包可以避免使用全局变量,还能将函数与其所操作的数据关连起来
装饰器(decorator)也称装饰函数,是一种闭包的应用,其主要是用于某些函数需要拓展功能,但又不希望修改原函数,它就是语法糖,使用它可以简化代码、增强其可读性,当然装饰器不是必须要求被使用的,不使用也是可以的,Python 中装饰器通过
@
符号来进行标识。
装饰器可以基于函数实现也可基于类实现,其使用方式基本是固定的,看一下基本步骤:
- 定义装饰函数(类)
- 定义业务函数
- 在业务函数上添加
@装饰函数(类)名
1)基于函数
# 装饰函数
def funA(fun):def funB(*args, **kw):print('函数 ' + fun.__name__ + ' 开始执行')fun(*args, **kw)print('函数 ' + fun.__name__ + ' 执行完成')return funB@funA
# 业务函数
def funC(name):print('Hello', name)funC('Jhon')
装饰函数也是可以接受参数的
# 装饰函数
def funA(flag):def funB(fun):def funC(*args, **kw):if flag == True:print('==========')elif flag == False:print('----------')fun(*args, **kw)return funCreturn funB@funA(False)
# 业务函数
def funD(name):print('Hello', name)funD('Jhon')
2)基于类
class Test(object):def __init__(self, func):print('函数名是 %s ' % func.__name__)self.__func = funcdef __call__(self, *args, **kwargs):self.__func()
@Test
def hello():print('Hello...')hello()
Python 装饰器的 @...
相当于将被装饰的函数(业务函数)作为参数传入装饰函数(类)。
6.5 反射
参考博客:【测试开发】python系列教程:python反射
定义:通过字符串操作对象的数据和方法
作用:使用反射可以让用户,通过输入字符串,调用对象中的数据或者方法
python反射的四个方法
hasattr():判断对象是否含有字符串对应的数据或者功能
getattr():根据字符串获取对应的变量名或者函数名
setattr():根据字符串给对象设置数据 (名称空间的名字)
delattr():根据字符串删除对象对应的数据 (名称空间中的名字)
user = User()
while True:choose = input('>>>').strip()if hasattr(user,choose):func = getattr(user,choose)func()else:print('输入错误。。。。')
class Dog():name='123'def printagename(self):print('111')
# 1.获取类中的值
print(getattr(Dog,'name'))
# 2.获取类中的方法
print(getattr(Dog,'printagename'))
# 3.调用
a=Dog()
getattr(Dog,'printagename')(a)
# 4.获取对象中的方法
print(getattr(a,'name'))
class Dog():name='123'def printagename(self):print('111')
# 1.获取类中的值
print(getattr(Dog,'name'))
#2.通过反射修改
setattr(Dog,'name','addddd')
#3.获取修改后结果
print(getattr(Dog,'name'))
class Dog():name='123'def printagename(self):print('111')
# 1.获取类中的值
print(getattr(Dog,'name'))
#2.通过反射删除
delattr(Dog,'name')
#3.获取修改后结果
print(getattr(Dog,'name'))
考虑有这么一个场景:需要根据用户输入url的不同,
调用不同的函数,实现不同的操作,
也就是一个WEB框架的url路由功能。
路由功能是web框架里的核心功能之一,例如Django的urls。
class url:def login():print("这是一个登陆页面!") def logout():print("这是一个退出页面!") def home():print("这是网站主页面!")def run():inp = input("请输入您想访问页面的url: ").strip()if inp == "login":url.login()elif inp == "logout":url.logout()elif inp == "home":url.home()else:print("404")if __name__ == '__main__':run()
可以通过反射来实现
class url:def login():print("这是一个登陆页面!") def logout():print("这是一个退出页面!") def home():print("这是网站主页面!")def run():inp = input("请输入您想访问页面的url:").strip()func = getattr(url, inp)func()if __name__ == '__main__':run()
7 模块
参考博客:详解Python模块化——模块(Modules)和包(Packages)
模块是包含 Python 定义和语句的文件。以.py为后缀的文件名就是模块名称
在模块内,模块的名称可以用全局变量 __name__
表示(字符串)
fibo.py
# Fibonacci numbers moduledef fib(n): # write Fibonacci series up to na, b = 0, 1while a < n:print(a, end=' ')a, b = b, a+bprint()def fib2(n): # return Fibonacci series up to nresult = []a, b = 0, 1while a < n:result.append(a)a, b = b, a+breturn result
fibo.py就是一个模块,fib、fib2是fibo模块中的函数
7.1 导入模块
①导入整个模块
import fibo
可使用下面的语法来使用其中任何一个函数:
fibo.fib(10) # 模块名+句点不可省略
②导入模块中的特定函数
from fibo import fib, fib2
fib(20)
③导入模块中的所有函数
from fibo import * # 这种方式会导入除可下划线 (__)开头的名称以外的所有函数
fib(20)
给导入的模块一个别名
import numpy as np
单独运行模块
可以在模块中添加以下代码,就可以既用作脚本,也可用作可导入模块:
if __name__ == "__main__":import sysfib(int(sys.argv[1]))
7.2 常用模块
参考博客:Python常用模块大全(总结)
7.2.1 文件处理
Python 的os
模块提供了各种操作系统的接口,这些接口主要是用来操作文件和目录
→ os.getcwd()
查看当前路径
import os
print(os.getcwd())
→ os.listdir(path)
返回指定目录下包含的文件和目录名列表
import os
print(os.listdir('D:/'))
→ os.path.abspath(path)
返回路径 path 的绝对路径
import os
# 当前路径(相对路径方式)
print(os.path.abspath('.'))
→ os.path.split(path)
将路径 path 拆分为目录和文件两部分,返回结果为元组类型
import os
print(os.path.split('E:/tmp.txt'))
→ os.path.join(path, *paths)
将一个或多个 path(文件或目录) 进行拼接
import os
print(os.path.join('E:/','a.txt'))
→ os.path.getmtime(path)
返回 path(文件或目录)的最后修改时间
import os
import datetime
print(datetime.datetime.utcfromtimestamp(os.path.getatime('E:/tmp.txt')))
→ os.path.exists(path)
判断 path(文件或目录)是否存在,存在返回 True,否则返回 False
import os
print(os.path.exists('E:/tmp.txt'))
→ os.path.isdir(path)
判断 path 是否为目录
import os
print(os.path.isdir('E:/'))
→ os.path.isfile(path)
判断 path 是否为文件
import os
print(os.path.isfile('E:/tmp.txt'))
→ os.path.getsize(path)
返回 path 的大小,以字节为单位,若 path 是目录则返回 0
import os
print(os.path.getsize('E:/'))
print(os.path.getsize('E:/'))
→ os.mkdir()
创建一个目录
import os
os.mkdir('E:/a')
→ os.makedirs()
创建多级目录
import os
os.makedirs('E:/test1/test2')
→ os.chdir(path)
将当前工作目录更改为 path
import os
print(os.getcwd())
os.chdir('/test')
print(os.getcwd())
→ os.system(command)
调用 shell 脚本
import os
print(os.system('ping www.baidu.com'))
7.2.2 日期时间
🍉 time 模块
localtime() 表示当前时间,返回类型为 struct_time 对象
import time
t = time.localtime()
print('t-->', t)
print('tm_year-->', t.tm_year)
print('tm_year-->', t[0])
常用函数:
import timeprint(time.time())
print(time.gmtime())
print(time.localtime())
print(time.asctime(time.localtime()))
print(time.tzname)
# strftime 使用
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
strftime 函数日期格式化符号说明如下所示:
🍉 datetime 模块
datatime 模块重新封装了 time 模块,提供了更多接口,变得更加直观和易于调用
(1)date 类
import datetime
import timeprint(datetime.date.today())
print(datetime.date.fromtimestamp(time.time()))
print(datetime.date.min)
print(datetime.date.max)
实例方法和属性如下所示:
import datetimetd = datetime.date.today()
print(td.replace(year=1945, month=8, day=15))
print(td.timetuple())
print(td.weekday())
print(td.isoweekday())
print(td.isocalendar())
print(td.isoformat())
print(td.strftime('%Y %m %d %H:%M:%S %f'))
print(td.year)
print(td.month)
print(td.day)
(2)time 类
time 类表示由时、分、秒、微秒组成的时间,格式为:time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
实例方法和属性如下所示:
import datetimet = datetime.time(10, 10, 10)
print(t.isoformat())
print(t.replace(hour=9, minute=9))
print(t.strftime('%I:%M:%S %p'))
print(t.hour)
print(t.minute)
print(t.second)
print(t.microsecond)
print(t.tzinfo)
(3)datetime 类
datetime 包括了 date 与 time 的所有信息,格式为:datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
类方法和属性如下所示:
import datetimeprint(datetime.datetime.today())
print(datetime.datetime.now())
print(datetime.datetime.utcnow())
print(datetime.datetime.fromtimestamp(time.time()))
print(datetime.datetime.utcfromtimestamp(time.time()))
print(datetime.datetime.combine(datetime.date(2019, 12, 1), datetime.time(10, 10, 10)))
print(datetime.datetime.min)
print(datetime.datetime.max)
实例方法和属性如下所示:
import datetimetd = datetime.datetime.today()
print(td.date())
print(td.time())
print(td.replace(day=11, second=10))
print(td.weekday())
print(td.isoweekday())
print(td.isocalendar())
print(td.isoformat())
print(td.strftime('%Y-%m-%d %H:%M:%S .%f'))
print(td.year)
print(td.month)
print(td.month)
print(td.hour)
print(td.minute)
print(td.second)
print(td.microsecond)
print(td.tzinfo)
🍉 calendar 模块
calendar 模块提供了很多可以处理日历的函数
(1)常用函数
import calendarcalendar.setfirstweekday(1)
print(calendar.firstweekday())
print(calendar.isleap(2019))
print(calendar.leapdays(1945, 2019))
print(calendar.weekday(2019, 12, 1))
print(calendar.monthrange(2019, 12))
print(calendar.month(2019, 12))
print(calendar.prcal(2019))
(2)Calendar 类
Calendar 对象提供了一些日历数据格式化的方法,实例方法如下所示:
from calendar import Calendarc = Calendar()
print(list(c.iterweekdays()))
for i in c.itermonthdates(2019, 12):print(i)
(3)TextCalendar 类
TextCalendar 为 Calendar子类,用来生成纯文本日历。实例方法如下所示:
from calendar import TextCalendartc = TextCalendar()
print(tc.formatmonth(2019, 12))
print(tc.formatyear(2019))
(4)HTMLCalendar类
HTMLCalendar 类可以生成 HTML 日历。实例方法如下所示:
from calendar import HTMLCalendarhc = HTMLCalendar()
print(hc.formatmonth(2019, 12))
print(hc.formatyear(2019))
print(hc.formatyearpage(2019))
7.2.3 sys模块
sys 模块主要负责与 Python 解释器进行交互,该模块提供了一系列用于控制 Python 运行环境的函数和变量
🍎 argv
返回传递给 Python 脚本的命令行参数列表
import sysif __name__ == '__main__':args = sys.argvprint(args)print(args[1])
🍎 version
返回 Python 解释器的版本信息
🍎 winver
返回 Python 解释器主版号
🍎 platform
返回操作系统平台名称
🍎 path
返回模块的搜索路径列表
🍎 maxsize
返回支持的最大整数值
🍎 maxunicode
返回支持的最大 Unicode 值
🍎 copyright
返回 Python 版权信息
🍎 modules
以字典类型返回系统导入的模块
🍎 byteorder
返回本地字节规则的指示器
🍎 executable
返回 Python 解释器所在路径
import sys#print(sys.version)
#print(sys.winver)
#print(sys.platform)
#print(sys.path)
#print(sys.maxsize)
#print(sys.maxunicode)
#print(sys.copyright)
#print(sys.modules)
print(sys.byteorder)
print(sys.executable)
🍎 stdout
标准输出
import syssys.stdout.write('Hi' + '\n')
print('Hi')
🍎 stdin
标准输入
import syss1 = input()
s2 = sys.stdin.readline()
print(s1)
print(s2)
🍎 exit()
退出当前程序
import sys
print('Hi')
sys.exit()
print('John')
🍎 getdefaultencoding()
返回当前默认字符串编码的名称
🍎 getrefcount(obj)
返回对象的引用计数
🍎 getrecursionlimit()
返回支持的递归深度
🍎 getsizeof(object[, default])
以字节为单位返回对象的大小
🍎 setswitchinterval(interval)
设置线程切换的时间间隔
🍎 getswitchinterval()
返回线程切换时间间隔
import sys
print(sys.getdefaultencoding())
print(sys.getrefcount('123456'))
print(sys.getrecursionlimit())
print(sys.getsizeof('abcde'))
sys.setswitchinterval(1)
print(sys.getswitchinterval())
8 包
参考博客:python导包的几种方法 自定义包的生成以及导入详解
8.1 导入包
🍉 import 常规导入,直接导入整个包的所有的功能函数
import time
time.time()
🍉 import多个导入,导入多个包的所有功能函数
import random, time
🍉 from … import …导入整个包的部分功能函数
from random import randint
from time import time, localtime
🍉 通过from … import * 这个也是直接导入包的所有功能。相当于import …
from time import *
8.2 生成包
🍉 在实际的应用中用得也是比较多的,我们自定义我们自己写的功能包
首先在任意路径创建一个文件夹,来放我们自定义的包的文件
创建在/home/xyh/test_package,下边是目录结构。要在另一个不相关的文件夹下的python应用中引用到我们自定义的包。就是在/home/xyh/test_package2/use_lucky_package.py中导入lucky_package.py这个包,测试直接import lucky_package.py或者直接from test_package import lucky_package.py是不行的
直接导入,出现程序运行错误提示信息
要想成功导入需要做的两步:
① 在test_package文件夹中创建__init__.py文件,里边什么都不需要编辑
② 在代码中把test_package的文件的路径加入到python解释器可以搜索到的路径列表中,这里就用到了python的包sys模块
下边是运行过一次的目录结构:pyc文件是py文件编译后生成的字节码文件,不需要自己创建,在你第一次成功导入包并运行成功之后会自动生成
lucky_package.py
#_*_coding:utf-8_*_
# 导入random模块,我们要制作的包要用
import random# 定义自定义包模块的简单功能
def test():print(random.randint(1,10))return('hello world')
use_lucky_package.py
#_*_coding:utf-8_*_
import sys# 动态添加test_package文件夹的路径,为了能让此文件夹下的
# 自定义包成功的导入
# 要根据你自己的实际包的模块来决定路径。
sys.path.append('../')# 打印所有python解释器可以搜索到的所有路径
print(sys.path)# 导入自定义包
from test_package.lucky_package import *# 输出lucky_package中test函数的结果:
result = test()
print(result)
9 异常处理
🥝 错误
- 语法错误
- 逻辑错误
🥝 异常
即便 Python 程序的语法是正确的,在运行它的时候,也有可能发生错误,运行期检测到的错误被称为异常;大多数的异常都不会被程序处理,都以错误信息的形式展现
BaseException+-- SystemExit+-- KeyboardInterrupt+-- GeneratorExit+-- Exception+-- StopIteration+-- StopAsyncIteration+-- ArithmeticError| +-- FloatingPointError| +-- OverflowError| +-- ZeroDivisionError+-- AssertionError+-- AttributeError+-- BufferError+-- EOFError+-- ImportError| +-- ModuleNotFoundError+-- LookupError| +-- IndexError| +-- KeyError+-- MemoryError+-- NameError| +-- UnboundLocalError+-- OSError| +-- BlockingIOError| +-- ChildProcessError| +-- ConnectionError| | +-- BrokenPipeError| | +-- ConnectionAbortedError| | +-- ConnectionRefusedError| | +-- ConnectionResetError| +-- FileExistsError| +-- FileNotFoundError| +-- InterruptedError| +-- IsADirectoryError| +-- NotADirectoryError| +-- PermissionError| +-- ProcessLookupError| +-- TimeoutError+-- ReferenceError+-- RuntimeError| +-- NotImplementedError| +-- RecursionError+-- SyntaxError| +-- IndentationError| +-- TabError+-- SystemError+-- TypeError+-- ValueError| +-- UnicodeError| +-- UnicodeDecodeError| +-- UnicodeEncodeError| +-- UnicodeTranslateError+-- Warning+-- DeprecationWarning+-- PendingDeprecationWarning+-- RuntimeWarning+-- SyntaxWarning+-- UserWarning+-- FutureWarning+-- ImportWarning+-- UnicodeWarning+-- BytesWarning+-- ResourceWarning
9.1 捕获异常
Python 程序捕捉异常使用 try/except 语句
#1、被除数为 0,未捕获异常
def getNum(n):return 10 / n
print(getNum(0))
#输出结果:ZeroDivisionError: division by zero#2、捕获异常
def getNum(n):try:return 10 / nexcept IOError:print('Error: IOError argument.')except ZeroDivisionError:print('Error: ZeroDivisionError argument.')
print(getNum(0))
'''
输出结果:
Error: ZeroDivisionError argument.
None
'''
try 语句的工作方式为:
- 首先,执行 try 子句 (在 try 和 except 关键字之间的部分)
- 如果没有异常发生, except 子句 在 try 语句执行完毕后就被忽略了
- 如果在 try 子句执行过程中发生了异常,那么该子句其余的部分就会被忽略
- 如果异常匹配于 except 关键字后面指定的异常类型,就执行对应的except子句,然后继续执行 try 语句之后的代码
- 如果发生了一个异常,在 except 子句中没有与之匹配的分支,它就会传递到上一级 try 语句中
- 如果最终仍找不到对应的处理语句,它就成为一个 未处理异常,终止程序运行,显示提示信息
9.2 try…else…finally结构
try/except 语句还可以带有一个 else、finally子句,示例如下:
def getNum(n):try:print('try --> ',10 / n)except ZeroDivisionError:print('except --> Error: ZeroDivisionError argument.')else:print('else -->')finally:print('finally -->')'''
1、调用:getNum(0)
输出结果:
except --> Error: ZeroDivisionError argument.
finally -->2、调用:getNum(1)
输出结果:
try --> 10.0
else -->
finally -->
'''
其中,else 子句只能出现在所有 except 子句之后,只有在没有出现异常时执行;finally 子句放在最后,无论是否出现异常都会执行
9.3 自定义异常
🍉 抛出异常
使用 raise 语句允许强制抛出一个指定的异常,要抛出的异常由 raise 的唯一参数标识,它必需是一个异常实例或异常类(继承自 Exception 的类),如:
raise NameError('HiThere')
🍉 自定义异常
正常来说,Python 提供的异常类型已经满足我们的使用了,但是有时候我们有定制性的需求,我们可以自定义异常类,继承自 Error 或 Exception 类就可以了,看个例子:
#自定义异常类 MyExc
class MyExc(Exception): #继承Exception类def __init__(self, value):self.value = valuedef __str__(self):if self.value == 0:return '被除数不能为0'
#自定义方法
def getNum(n):try:if n == 0:exc = MyExc(n)print(exc)else:print(10 / n)except:pass
getNum(1)
getNum(0)
在这个自定义的异常例子中,当参数 n 不为 0 时,则正常,当 n 等于 0,则抛出异常,自定义异常在实际应用中很少用到,了解即可
10 文件操作
参考博客:Python文件读写详解(非常详细)
(1)打开文件
使用open()函数来打开文件。open()函数接受两个参数,第一个是文件名,第二个是打开文件的模式。常见的模式有:
- ‘r’: 只读模式,用于读取文件内容。
- ‘w’: 写入模式,用于写入文件内容。如果文件不存在,会创建一个新文件;如果文件已存在,会清空文件内容。
- ‘a’: 追加模式,用于在文件末尾添加内容。如果文件不存在,会创建一个新文件。
- ‘b’: 二进制模式,用于处理二进制文件,如图片、视频等。
# 以只读模式打开文件
file = open('example.txt', 'r')
# 以写入模式打开文件(如果文件不存在则创建)
file = open('example.txt', 'w')
# 以追加模式打开文件(如果文件不存在则创建)
file = open('example.txt', 'a')
# 以二进制模式打开文件
file = open('example.jpg', 'rb')
(2)读取文件内容
1 读取整个文件
with open('example.txt', 'r') as file: content = file.read() print(content)
2 逐行读取
使用readline()方法可以逐行读取文件的内容
with open('example.txt', 'r') as file: line = file.readline() while line: print(line) line = file.readline()
3 读取所有行
使用readlines()方法可以将文件的所有行读取到一个列表中
with open('example.txt', 'r') as file: lines = file.readlines() for line in lines: print(line)
(3)写入文件内容
1 写入单行
with open('example.txt', 'w') as file:file.write('Hello, World')
2 写入多行
使用writelines()方法可以将多行内容写入文件
lines = ['Line 1\n', 'Line 2\n', 'Line 3\n']
with open('example.txt', 'w') as file: file.writelines(lines)
(4)文件迭代器
文件对象是可迭代的,因此我们可以使用for循环逐行读取文件内容
with open('example.txt', 'r') as file:for line in file:print(line)
(5)上下文管理器(Context Manager)
使用with语句打开文件,可以确保在文件使用完毕后自动关闭文件,避免资源泄漏
with open('example.txt', 'r') as file: content = file.read() print(content) # 文件自动关闭
(6)异常处理
在文件读写过程中,可能会出现异常,例如文件不存在或权限错误。因此,在操作文件时,最好使用异常处理来增强程序的健壮性
try: with open('example.txt', 'r') as file: content = file.read() print(content)
except FileNotFoundError: print('文件不存在!')
except PermissionError: print('无权限访问文件!')
except Exception as e: print(f'发生未知错误:{e}')
(7)关闭文件
虽然使用with语句可以确保文件被正确关闭,但在某些情况下,可能需要手动关闭文件
file = open('example.txt', 'r')
content = file.read()
print(content)
file.close() # 手动关闭文件
(8)二进制文件操作
with open('example.jpg', 'rb') as file: data = file.read() # 对二进制数据进行操作
(9)文件定位
在文件读写中,有时候需要移动文件指针的位置,可以使用seek()方法
with open('example.txt', 'r') as file: content = file.read(10) # 读取前10个字符 print(content) file.seek(0) # 移动文件指针到文件开头 content = file.read(5) # 再次读取前5个字符 print(content)
以上详解了Python基础,不正之处望读者指教