面向对象(下)

目录

私有化属性

私有化方法

Property属性

new实例化方法

单例模式

错误和异常处理

自定义异常

动态添加属性和方法

slots属性限制

作业


私有化属性 

加两个下划线将此属性私有化

使用私有属性的场景

1.把特点的一个属性隐藏起来,不想让类的外部进行直接调用

2.我想保护这个属性,不想让属性的值随意改变

3.保护这个属性,不想让子类去继承

class Person:
    __hobby='跳舞'
    def __init__(self):
        self.__name='李四' #加两个下划线将此属性私有化,不能在外面访问
        self.age='30'
        pass
    def __str__(self):
        '''
        私有化属性可以在内部使用
        :return:
        '''
        return '%s的年龄是%s,爱好是%s'%(self.__name,self.age,self.__hobby)
    def change(self):
        Person.__hobby='唱歌' #修改私有属性的值
class student(Person):
    def printInfo(self):
        print(self.__name) #说明子类不能访问父类的私有属性
    pass


# xl=Person()
# #print(xl.__name)#通过类对象在外部访问,不能访问私有属性
# print(xl)

Stu=student()
Stu.change()
print(Stu)

结论 :

1.私有化的实例属性,不能在外部直接访问,可以在内部随意使用

2.子类不能继承父类的私有化属性,只能继承父类的公共属性

3.在属性名的前面,直接加俩个下划线,就可以变为私有化

私有化方法

class Animal:
    def eat(self):
        self.__run() #内部调用私有化方法
        print('吃东西')
        pass
    def __run(self):
        print('飞快的跑')
        pass
class Bird(Animal):
    pass

b=Bird()
b.eat()
#b.run() #调用私有化方法,报错

通过外面实例对象调用私有属性会报错。

Property属性

通过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)

    #实现方式二 通过装饰器去实现
    @property #用装饰器修饰,添加属性标志 #提供一个getter的方法
    def age(self):
        return self.__age
    @age.setter #提供一个getter方法
    def age(self,parms):
        if parms < 0:
            print('年龄不能小于0')
        else:
            self.__age = parms
            pass
        pass
    pass

p1=Person()
print(p1.age)
p1.age=25
print(p1.age)

new实例化方法

_new_方法的作用是,创建并返回一个实例对象,如果__new__只调用了一次,就会得到一个对象。继承自object的新式类才有new这一魔法方法。

注意事项:

1.__new__ 是在一个对象实例化的时候所调用的第一个方法

2.__new__至少必须要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供 ,其他的参数是用来直接传递给 __init__ 方法

3.__new__ 决定是否要使用该 __init__ 方法,因为 __new__ 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 __new__ 没有返回实例对象,则 __init__ 不会被调用

4.在__new__ 方法中,不能调用自己的__new__ 方法,即:return cls.__new__ (cls),否则会报错(RecursionError: maximum recursion depth exceeded:超过最大递归深度)

class Animal:
    def __init__(self):
        self.color='红色'
        pass
    #在python当中,如果不重写__new__的默认结构如下:
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs) #不能用cls创建
       # return object.__new__(cls, *args, **kwargs)
    pass
tigger=Animal() #实例化的过程会自动调用new去创建实例

单例模式

单例模式 --是一种常用的软件设计模式

目的:确保某一个类只有一个实例存在 ,如果希望在整个系统中,某个类只能出现一个实例的时候,那么这个单例对象就满足要求。

class DataBaseClass(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_instance'): #如果不存在_instance,才去创建
            cls._instance=super().__new__(cls, *args, **kwargs)
        return cls._instance
    pass
class DBoptSingle(DataBaseClass):
    pass


db1=DataBaseClass()
print(id(db1))
db2=DataBaseClass()
print(id(db2))
db3=DataBaseClass()
print(id(db3))

错误和异常处理 

语法:

try: 可能出现错误的代码块

except: 出错之后执行的代码块

else: 没有出错的代码块

finally: 不管有没有出错都执行的代码块

except:

except 在捕获错误异常的时候,只要根据具体的错误类型来捕获的 用一个块,可以捕获多个不同类型的异常.

Exception可以捕获所有的异常,当对出现的问题或者错误异常不确定下,可以用Excetion。

try:
    #print(b) #捕获逻辑的代码
    #li=[1,2,3]
    #print(li[10]) #通过下标访问列表
    a=10/0
    pass
except NameError as msg:
    #捕获到的错误,才会在这里执行
    print(msg)
    pass
except IndexError as msg:
    print(msg)
    pass
except ZeroDivisionError as msg:
    print(msg)
   pass
except Exception as result: #Exception包括所有类型
    print(result)

不需要在每个可能出错的地方去捕获,只要在合适的层次去捕获错误就可以了,这样的话,就可以大大减少我们try---exception

异常抛出机制:

1.如果在运行时发生异常,解释器会查找相应的异常捕获类型

2.如果在当前函数里没有找到的话,它会将异常传递给上层的调用函数

3.如果在最外层,没有找到的话,解释器就会退出

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)
        pass
    pass
main()

自定义异常 

自定义异常,都要直接或间接继承Error或Exception类。

由开发者主动抛出自定义异常,在python中使用raise关键字。

class ToolongMyException(Exception):
    def __init__(self,leng):
        '''

        :param long:长度
        '''
        self.len=leng
        pass
    def __str__(self):
        return '你输入的姓名数据长度是'+str(self.len)+'超过长度了'
    pass
def name_Test():
    name=input('请输入姓名:')
    try:
        if len(name)>5:
            raise ToolongMyException(len(name))
        else:
            print(name)
            pass
        pass
    except ToolongMyException as result:
        print(result)
        pass
    finally:
        print('执行完毕')

name_Test()

动态添加属性和方法

import types #添加方法的库


def dymicMethod(self):
    print('%s的体重是%s,在%s读大学'%(self.name,self.weight,Student.shcool))
    pass
@classmethod
def classTest(cls):
    print('这是一个类方法')
    pass

@staticmethod
def staticMethodTest():
    print('这是一个静态方法')
    pass



class Student:
    def __init__(self,name,age):
        self.name=name
        self.age=age
        pass
    pass
    def __str__(self):
        return '%s今天%s岁了'%(self.name,self.age)
    pass
zyh=Student('张燕华',20)
zyh.weight=50 #动态 添加
zyh.printInfo=types.MethodType(dymicMethod,zyh)#动态的绑定方法
# print(zyh)
# print(zyh.weight)


print('-----------另一个实例对象 张明------------')
zm=Student('张明',20)
print(zm)
#print(zm.weight)#报错 weight是zyh特有的

print('-----------类对象添加属性------------')
Student.shcool='北京邮件大学' #动态添加类属性
print(zm.shcool)


print('-----------执行动态调用的方法------------')
zyh.printInfo() #调用动态绑定的方法

print('绑定类方法')
Student.TestMethod=classTest
Student.TestMethod()
print('绑定类方法结束')

zyh.TestMethod()
print('---------实例对象调用动态绑定类方法--------')

print('绑定静态方法')
Student.staticMethod=staticMethodTest
Student.staticMethod()
print('绑定静态方法结束')

 代码中写了,如何动态绑定方法和动态添加属性。

slots属性限制

作用:

1.限制要添加的实例属性

2.节约内存空间

class Student(object):
    __slots__ = ('name','age')
    def __str__(self):
        return '%s   %s'%(self.name,self.age)
    pass

xw=Student()
xw.name='小王'
xw.age=20
#xw.score=96 #slot已经限制,无法添加,所以会报错
#print(xw.__dict__)#所以可以用的属性都在这里存储,不足的地方就是占用的空间大,当slots存在时,这里没有意义,会报错
print(xw)

在继承关系中slots的使用:

子类未声明__slots__时,那么是不会继承父类的__slots__,此时子类可以随意的属性赋值的。

子类声明了__slots__时,继承父类的__slots__,也就是子类的__slots__的范围是为其自身+父类__slots__的并集。

课后作业

1、编写一段代码以完成下面的要求

 定义一个Person类,类中要有初始化方法,方法中要有人的姓名,年龄两个私有属性.

提供获取用户信息的函数. 

提供获取私有属性的方法.

 提供可以设置私有属性的方法. # 设置年龄的范围在(0-120)的方法,如果不在这个范围,不能设置成功.

 

class Person:
    def __init__(self,n,a):
        '''

        :param n:
        :param a:
        '''
        self.__name=n
        self.__age=a
        pass
    def __str__(self):
        return '{}的年龄是:{}'.format(self.__name,self.__age)
    def getAgeInfo(self):
        return self.__age
    def setAge(self,age):
        if age>0 and age<120:
            self.__age=age
            pass
        else:
            print('您输入的数据不合法')
    def getNameInfo(self):
        return self.__name
    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
    def __str__(self):
        return self.__name
    def __call__(self, *args, **kwargs):
        # print(self.__name+'的得分是:'+(str)self.__score)
        print('{}的得分是:{}'.format(self.__name,self.__score))
        pass
    pass

# xw=Student()
# xw() #将实例对象以函数的形式去调用
# xw.name='李四'
# xw.score=98
# xw()
# print(xw)

3. 创建一个Animal类,实例化一个cat对象,请给cat对象动态绑定一个run方法,给类绑定一个类属性colour,给类绑定一个类方法打印字符串'ok'。

import types
def run(self):
    print('小猫飞快的跑...')
    pass
@classmethod
def info(cls):
    print('ok')
class Animal:
    pass

Animal.colour='黑色'#绑定类属性
Animal.info=info
cat=Animal()
cat.run=types.MethodType(run,cat) #动态绑定
cat.run()
print(cat.colour)
Animal.info()

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值