目录
(二)try---except----else 没有错时执行else
(三) try---except----finally 不管有无错,都要执行finally
一、属性和方法的私有化
(一)、属性私有化
使用私有属性的场景: 1.把特定的一个属性隐藏起来 不想让类的外部进行直接调用 2.我想保护这个属性 不想让属性的值随意的改变 3.保护这个属性 不想让子类[派生类]去继承
class Person:
__hobby='跳舞' # 私有类属性
def __init__(self):
self.__name='李四' # 加两个下划线 将此属性私有化之后 就不能在外部直接访问了
self.age=30
pass
def __str__(self):
return '{}的年龄是{},爱好是{}'.format(self.__name,self.age,Person.__hobby)
def changeValue(self):
Person.__hobby='唱歌'
pass
def printName(self):
print(self.__name) #调用此方法就可以间接打印self.__name
xl=Person()
# print(xl.__name) # 是通过类对象在外部访问 不成立
print(xl) # 李四的年龄是30,爱好是跳舞
xl.changeValue() # 这样可以更改
print(xl) # 李四的年龄是30,爱好是唱歌
xl.printName() # 李四
class Student(Person):
def printInfo(self):
print(self.__name) # 在此可以访问父类私有属性吗? 不能
pass
stu=Student()
print(stu.age) # 30
# print(stu.__name) # 错误 私有属性不能继承
# print(stu.printInfo()) # 报错了 'Student' object has no attribute '_Student__name'
# print(stu.__hobby) #报错 不能访问
# print(Person.__hobby) #报错 不能访问
小结:
1.私有化的[实例]属性 不能再外部直接的访问 可以在类的内部随意使用
2.不能继承父类的私有化属性[只能继承父类公共的属性和行为]
3.在属性名前直接加'__',就变成私有化属性
(二)私有化方法
私有化方法和私有化属性类似:
# 私有化方法
class Animal:
def __eat(self): # 私有化方法
print('吃东西')
pass
def Neibudiaoyong__eat(self):
self.__eat()
pass
def run(self):
print('飞快的跑')
pass
class Bird(Animal):
pass
b1=Bird()
# print(b1.__eat()) #报错 不能在外部直接调用私有方法
b1.Neibudiaoyong__eat() # 吃东西 通过类的内部调用私有方法
二、属性函数Property
(实现方法一)
# 实现方式一
class Person(object):
def __init__(self):
self.__age=18 #定义一个私有化属性,属性名字前加两个下划线__
def get_age(self):
return self.__age
def set_age(self,age):
if age<0:
print('年龄不能小于0')
else:
self.__age=age
pass
pass
# 定义一个类属性 实现通过访问属性的形式去访问私有的属性
age=property(get_age,set_age)
pass
p1=Person()
print(p1.age) # 18 这样就可以访问了 通过property调用get_age
p1.age=20 # 通过property调用set_age
print(p1.age) #20
p1.age=-1
print(p1.age)
运行结果:
(实现方法二)
# 实现方式二
class Person(object):
def __init__(self):
self.__age=18 #定义一个私有化属性,属性名字前加两个下划线__
@property # 用装饰器 添加属性标识 提供一个getter方法
def age(self):
return self.__age
@age.setter #提供一个setter方法
def age(self,parms):
if parms < 0:
print('年龄不能小于0')
else:
self.__age=parms
pass
pass
p2=Person()
print(p2.age) # 18 相当于调用age函数
p2.age=20 # 通过装饰器 调用 第二个age函数 (age.setter)
print(p2.age) #20
三、__new__方法
# __new__方法
class Animal:
def __init__(self):
self.color='红色'
pass
# 在python当中 如果不重写 __new__ 默认结构如下
def __new__(cls, *args, **kwargs):
return super().__new__(cls,*args,**kwargs)
# 等同于return object.__new__(cls,*args,**kwargs)\
pass
tigger=Animal() #实例化的过程会自动调用__new__去创建实例
在新式类中__new__才是真正的实例化的方法 为类提供外壳制造出实例框架,然后调用该框架内的构造方法__init__进行丰满操作
比喻建房子__new__ 方法负责开发地皮 打地基 并将原料存放在工地;
__init__负责从工地取材料建造出地皮开发图纸规定的大楼 细节设计、建造 最终完成
四、单例模式
简介: 1.是一种常用的软件设计模式 2.目的:确保某个类只有一个实例存在 3.如果希望在整个系统中某个类只能出现一个实例的时候,那么这个单例对象就满足要求
class DataBaseClass(object):
def __new__(cls, *args, **kwargs):
# cls._instance=cls.__new__(cls) #不要使用自身的new方法
# 容易造成一个深度递归,应该调用父类的new方法
if not hasattr(cls,'_instance'): #如果不存在就开始创建
cls._instance=super().__new__(cls,*args,**kwargs)
return cls._instance
pass
class DataSingle(DataBaseClass):
pass
db1=DataBaseClass()
db2=DataBaseClass()
print(id(db1))
print(id(db2)) #两者内存地址相同 即为一个实例对象
ds3=DataSingle()
print(id(ds3)) #子类实例对象内存地址也和上面两个相同 也为同一个实例对象
五、异常处理
try 遇到第一个错误就会跳出,如果没有异常发生,忽略 except 子句,try 子句执行后结束 except 在捕获错误异常时, 要根据具体的错误类型来捕获 用一个块 可以捕获多个不同类型的异常 Exception 可以捕获所有类型的错误 当错误类型不清楚时使用
(一)try----except
try: #捕获逻辑的代码
li=[1,2,3,4]
print(li[10]) # 通过下标访问列表
pass
except Exception as msg: #Exception 可以拿来捕获所有类型异常 也有其他类型可以去了解一下
# 在此尽量去处理捕获到的错误
print(msg)
pass
print('后续代码正常进行')
运行结果:
也可以在函数调用中使用:
def A(s):
return 10/int(s)
pass
def B(s):
return A(s)*2
def MainError():
try:
B('0')
pass
except Exception as msg:
print(msg)
pass
pass
MainError() # 运行结果:division by zero
不需要再每个可能出现错误的地方去捕获,只要再合适的层次去捕获错误就可以了 减少try---except的麻烦 异常的抛出机制 如果在运行时发生异常 解释器会查找相应的异常捕获类型 如果在当前函数没有找到的话 它会将异常传递给上层的调用函数,看能否处理 如果在最外层没有找到的话,解释器就会退出 程序down掉
(二)try---except----else 没有错时执行else
# try---except----else
try:
print('我没有错误')
pass
except SyntaxError as msg:
print('error:',msg)
pass
except Exception as msg:
print('error:',msg)
pass
else:
print('当try里面代码 没有出现异常的情况下,我else才执行')
pass
运行结果:
(三) try---except----finally 不管有无错,都要执行finally
try:
int('fffffff')
pass
except Exception as msg:
print(msg)
pass
finally:
print('不管有没有出错,我finally都要执行')
运行结果:
(四)自定义异常
# 直接或间接继承Error类或者Exception类
class ToolongMyException(Exception):
def __init__(self,leng):
'''
:param leng:长度
'''
self.len=leng
pass
def __str__(self):
return '您输入姓名数据长度是'+str(self.len)+'超过限制长度5了..'
pass
def name_Test():
name=input('请输入姓名:')
try:
if len(name)>5:
raise ToolongMyException(len(name)) # raise语句用于抛出指定的异常
else:
print(name)
pass
pass
except ToolongMyException as msg:
print('Error:',msg)
finally:
print('执行完毕')
name_Test()
运行结果:
六 、动态绑定属性和方法
写一个Student类及一个实例对象
# 动态绑定属性和方法
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
pass
def __str__(self):
return '{}今年{}岁了'.format(self.name,self.age)
pass
zyh=Student('张艳华',18)
1.动态添加实例属性
zyh.weight=80 #动态添加实例属性
print(zyh)
print(zyh.weight)
运行结果
2.动态添加类属性
#动态添加类属性
print('----------给类对象添加属性-------------')
Student.school='重庆邮电大学'
print(zyh.school) # 可以访问 school
运行结果:
3.动态添加实例方法
# 动态添加实例方法
print('-----------动态添加实例方法-------------')
import types
def dymicMethod(self):
print('{}的体重是{}在{}学习'.format(self.name,self.weight,Student.school))
pass
zyh.printInfo = types.MethodType(dymicMethod,zyh) #动态绑定实例方法
zyh.printInfo() #张艳华的体重是80在重庆邮电大学学习 调用动态绑定的方法
运行结果:
4.动态添加类方法
# 动态添加类方法
print('-----------动态添加类方法-------------')
@classmethod
def classTest1(cls):
print('这是一个类方法')
pass
Student.TestMethod1=classTest1
Student.TestMethod1() #这是一个类方法
zyh.TestMethod1() #这是一个类方法 实例对象调用动态绑定类方法
运行结果:
5. 动态添加静态方法
# 动态添加静态方法
print('-----------动态添加静态方法-------------')
@staticmethod
def classTest2():
print('这是一个静态方法')
pass
Student.TestMethod2=classTest2
Student.TestMethod2() #这是一个静态方法
zyh.TestMethod2() #这是一个静态方法
运行结果:
七、__slots__属性限制
作用:
限制要添加的实例属性
可以节约内存空间
1.__slots__的使用和__dict__
class Student(object):
__slots__ = ('name','age') # 只允许实例对象动态添加 name和age两个属性
def __str__(self):
return '{}今年{}岁了'.format(self.name,self.age)
pass
xw=Student()
xw.name='小王'
xw.age=15
# xw.cuo='错误' #添加失败 AttributeError: 'Student' object has no attribute 'cuo'
print(xw) #运行结果:小王今年15岁了
# print(xw.__dict__) # 没有__slots__时 所有可用属性都在这里存储 占用内存空间大
# 注释掉__slots__后,print(xw.__dict__) 运行结果为{'name': '小王', 'age': 15}
# 在定义了slots变量之后 Student类的实例已经不能随意创建不在__slots__定义的属性了
# 同时还可以看到实例当中也不存在__dict__
2.继承关系中使用 __slots__
class sub1Student(Student):
pass
ln=sub1Student()
ln.gender='男'
ln.pro='统计学'
print(ln.gender,ln.pro) #男 生物信息学
class sub2Student(Student):
__slots__ = ('sex')
pass
dl=sub2Student()
dl.name='dl'
# dl.pro='统计学' #报错AttributeError: 'sub2Student' object has no attribute 'pro'
dl.sex='男'
print(dl.name,dl.sex) #dl 男
运行结果:
规律:
1.子类未声明 __slots__时,那么是不会继承父类的__slots__,此时子类是可以随意的属性赋值的
2.子类声明了 __slots__时,子类的__slots__范围 = 父类slots+子类自己声明的slots