PYTHON学习笔记(八)-- 面向对象(下)

  1. 私有化
  2. Property属性
  3. ——new——方法和单例模式
  4. 异常及错误处理
  5. 动态添加属性和方法
  6. __slots__属性
  7. 相关作业

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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值