- 私有化
- Property属性
- ——new——方法和单例模式
- 异常及错误处理
- 动态添加属性和方法
- __slots__属性
- 相关作业
1.私有化
私有化属性:
为了更好的保护属性安全,且不能随意修改,将属性定义为私有属性,添加一个可调用的方法去访问
使用场景:
1.把特定一个属性隐藏起来,不想让类的外部进行直接调用
2.要保护这个属性,不想让属性的值随意改变
3.保护这个属性,不想让派生类(子类)去继承
语法:两个下划线开头,不能在类的外部被使用或直接访问
class Person:
__hobby = '跳舞'#私有类属性规则一样
def __init__(self):
self.__name = '李四'#定义了私有属性,就不能在外部直接访问了
self.age = 30
pass
def __str__(self):
return '{}的年龄是{}'.format(self.__name,self.age)
#在类的内部可以通过在类内定义的方法使用,修改,访问
class Student(Person):
def printInfo(self):
print(self.__name)#定义方法也不可以调用父类私有属性
print(self.age)#可以调用实例属性
pass
xl = Person()
#print(xl.__name)#私有属性不能打印出来,报错
print(xl)#李四的年龄是30
sd = Student()
#print(sd.__name)#子类也不可以调用,不能继承
私有化方法
和私有化属性概念一样,有些重要方法,不允许外部调用,防止子类重写,便可以设置私有方法
语法与私有化属性一直,在前面加’——‘
class Animal:
def __eat(self):
print('恰饭')
pass
def run(self):
self.__eat()#在类的内部可以调用私有方法
print('跑步')
pass
class Tiger(Animal):
pass
ti = Tiger()
#ti.eat()#子类不可以调用私有方法
ti.run()
其他:
2. Property属性
通过Property属性,可以给予私有化属性一些访问和修改的操作
#实现方式1 -- 通过新定义属性并通过Property赋予方法
class Person:
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()
p1.get_age()
p1.set_age(35)
p1.age = 25#设定了以后便可以修改
print(p1.age)
#实现方式2,使用装饰器
class Animal:
def __init__(self):
self.__age = 20
@property #用装饰器修饰,添加属性标志,提供一个getter方法
def age(self):
return self.__age
@age.setter #使用装饰器对age装饰,提供一个setter方法
def age(self,age):
if age < 0:
print('年龄不能小于0')
else:
self.__age = age
pass
pass
3. ——new——方法和单例模式
new:
一个类,实例化的过程中会自动调用——new——去创建实例,再调用——init——初始化
单例模式:
是一种常见的软件设计模式 目的:确保某一类只有一个实例存在
若希望整个系统中,某个类只出现一个实例时,那么该实例对象就满足要求
#创建一个单例对象,基于__new__去事项
class DataBaseClass(object):
def __new__(cls, *args, **kwargs):
'''
cls._instance = cls.__new__(cls) 不能使用自身的new方法,
容易造成深度递归,应该调用父类的new方法
'''
if not hasattr(cls,'_instance'): #如果不存在才能创建对象
#相当于 if not cls._instance:
cls._instance = super().__new__(cls,*args,**kwargs)
#返回的始终都是一个对象
return cls._instance
pass
class DBo(DataBaseClass):
pass
#无论创建几个对象,地址值都是一样的,相当于还是同一个对象
db1 = DBo()
print(id(db1))
db2 = DBo()
print(id(db2))
db3 = DBo()
print(id(db3))
4.异常及错误处理
try:
可能会出错的代码块
except:
出错之后执行的代码块
else:
没有出错的代码块
finally:
无论是否出错都
try:
print(b)#没定义异常
li = [1,2,3]
print(li[10])#数组下标访问异常
a = 10/0#除零异常
pass
except NameError as msg:#对象没定义就是用属于nameerror的错误
print(msg)
print('函数没定义')
pass
except IndexError as msg:#下标访问异常属于IndexError
print(msg)
pass
except ZeroDivisionError as msg:#除0异常属于ZeroDivisionError
print(msg)
pass
except Exception as result:#万能异常类型,什么异常都可以用
#在此尽量处理捕获到的错误
print('all')
print(result)
else:
print('没有错误发生')
finally:
#一般用来释放文件的资源,数据库链接等
print('无论如何都会执行')
#对于方法异常处理
def A(s):
return 10/int(s)
pass
def B(s):
return A(s)*2
def main():
try:
B('0')
pass
except Exception as msg:
print(msg)
main()
#不需要在每个可能出错的地方去捕获,只需要在合适层次捕获即可
#异常抛出机制
#如果运行时发生异常 解释器会查找出相应的异常捕获类型
#若果在当前函数上没有找到 他会将异常异地给上层的调用函数
#如果在最外层 还没有找到的话,解释器就会退出
print('错误处理后,程序还能正常运行')
自定义异常:
#自定义异常
class TOOlongExceception(Exception):#自定义异常要继承于异常的基类
def __init__(self,leng):
self.len = leng
pass
def __str__(self):
return '你输入的数据长度是:'+str(self.len)+',超过长度了'
pass
def name_Test():
name = input('请输入姓名')
try:
if len(name)>5:#len()--输出数据长度
raise TOOlongExceception(len(name))#raise--抛出异常
else:
print(name)
pass
pass
except TOOlongExceception as mag:
print(mag)#你输入的数据长度是:7,超过长度了
pass
else:
print(name)
finally:
print('执行完毕')
name_Test()
5.动态添加属性和方法
动态添加属性:
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
pass
def __str__(self):
return '{}今天{}岁了'.format(self.name,self.age)
pass
xo = Student('小欧',20)
xo.weight = 80#通过实例对象,动态添加属性
print(xo)
print(xo.weight)
#当创建另外一个实例对象时,不能使用其他实例对象动态添加的属性
zm = Student('张明',19)
#print(zm.weight)#'Student' object has no attribute 'weight'
#通过类对象添加属性
Student.height = 180
print(zm.height)#通过类对象动态添加的属性,所有实例对象都可以使用
动态添加方法:
#动态添加方法必须先导入types库
import types
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
pass
def __str__(self):
return '{}今天{}岁了'.format(self.name,self.age)
pass
#定义方法以供动态添加
def dymicMethod(self):
print('{}的体重是{},身高是{}'.format(self.name,self.height,Student.weight))
#类添加的方法还是要通过类来引用
pass
#定义类方法动态添加
@classmethod
def classTest(cls):
print('动态添加类方法')
pass
#静态绑定静态方法
@staticmethod
def staticMethodTest():
print('动态绑定静态方法')
pass
xo = Student('xo',20)
Student.weight = 180
xo.height = 190
#对象动态绑定普通方法
#将右侧的方法绑定到左侧的对象对应方法名中
xo.printInfo = types.MethodType(dymicMethod,xo)#方法名,绑定的实例对象
#执行动态绑定的方法
xo.printInfo()
#动态绑定类方法
Student.TestMethod = classTest
Student.TestMethod()
xo.TestMethod()#动态绑定的类方法也是所有实例对象都可以调用的
#动态绑定静态方法,和动态绑定类方法操作一直
Student.StaticMethod = staticMethodTest
Student.StaticMethod()
6. __slots__属性
python是动态语言,在运行时可以动态添加属性。如果要限制在运行的时候给类添加户型,python允许在定义class时,定义一个特殊的slots变量,来限制class实力能添加的属性
只有在slots变量中的属性才能被添加,没有则添加失败,slots属性子类不会继承,只有在当前类中有效
限定了属性的定义,节约了内存空间
class Student(object):
__slots__ = ('name','age')#限定只能添加name和age属性
def __str__(self):
return '{}...{}'.format(self.name,self.age)
pass
xw = Student()
#动态添加实例属性
xw.name = '小王'
xw.age = 20
#xw.score = 96#不在slots范围内,无法添加
# --AttributeError: 'Student' object has no attribute 'score'
#print(xw.__dict__)#所有可以用的属性都在这存储,不足的是占用的内存空间大
#在把所有可用属性都存储到slots时,该魔术方法便被弃用
print(xw)
#在继承关系中使用 slots
#子类未声明slots时,是不会继承父类的slots的,此时子类可以任意添加属性
#子类声明了slots时,会继承父类的slots,也就是子类的slots = 子类新加的+父类本身有的
class subStudent(Student):
__slots__ = ()
pass
ln = subStudent()
ln.gender = '男'
7.相关作业
例1:编写一段代码以完成下列要求
·定义一个Person类,类中要有初始化方法,方法中要有人的姓名,年龄两个私有属性
·提供获取用户信息的函数
·提供获取私有属性的方法
·提供可以设置私有属性的方法
·设置年龄的范围在0-120的方法,如果不在这个范围内不能设置成功
class Person:
#类中要有初始化方法,方法中要有人的姓名,年龄两个私有属性
def __init__(self,n,a):
self.__name = n
self.__age = a
#提供获取用户信息的函数
def __str__(self):
return '{}‘s age is {}'.format(self.__name,self.__age)
#·提供获取私有属性的方法
def getAgeInfo(self):
return self.__age
def getNameInfo(self):
return self.__name
#提供可以设置私有属性的方法
def setAge(self,age):
#设置年龄的范围在0-120的方法,如果不在这个范围内不能设置成功
if age>0 and age<120:
self.__age = age
else:
print('年龄错误')
def setName(self,name):
self.__name = name
例2:创建一个类,并定义两个私有化属性,提供一个获取属性的方法,和设置属性的方法,利用property属性给调用者提供相关的操作
class Student:
def __init__(self):
self.__name = '张三'
self.__score = 90
pass
@property
def name(self):
return self.__name
@name.setter
def name(self,name):
self.__name = name
pass
@property
def score(self):
return self.__score
@score.setter
def score(self,score):
self.__score = score
pass
#另一种打印方法call,将对象以函数的方式打印
def __call__(self, *args, **kwargs):
print('{}的分数是{}'.format(self.__name,self.__score))
pass
pass
xw = Student()
xw()#执行call里面的内容--张三s score is90
xw.name='李四'
xw.score = 96
xw()
例3,创建一个animal类,实例化一个cat对象,给cat对象动态绑定一个run方法,
给类绑定一个类属性color
import types
def run(self):
print('跑起来松弟萌')
#绑定类方法
@classmethod
def Info(cls):
print('ok')
class Animal:
pass
cat = Animal()
#动态绑定类属性
Animal.color = 'black'
print(cat.color)
#动态绑定方法
cat.run = types.MethodType(run,cat)
cat.run()
#绑定类方法
Animal.Info = Info
Animal.Info()