AI学习 Day09 面向对象基础(下)
本文章最初发布在 XJHui’s Blog,未经允许,任何人禁止转载!
注意:最新修改版本已发布在 这里,点击前往查看!
私有化属性
有些属性不想让别人随意修改或者防止被意外修改,就要对属性进行私有化
基本概述
定义:
为了保证属性安全(不能被随意修改),可以将属性定义为私有属性
使用场景:
- 属性不想被类的外部直接调用
- 属性值不想随意被改变
- 不想被子类继承
语法:
class Person:
__name = ‘张三’ # 属性名前加两个下划线将该属性私有化
## 使用私有属性1. 案例:验证实例属性私有化后在类的外部不可调用```python
class Person:def __init__(self):self.name = '张三' # 实例属性self.__age = 17 # 私有属性passpassp1 = Person()
print(p1.name) # 打印实例属性
运行结果:
print(p1.age) # 打印私有属性
运行结果:
案例:验证私有化属性可在类的内部调用
class Person:def __init__(self):self.name = '张三'self.__age = 17passdef printData(self): # 实例方法,打印私有属性ageprint(self.__age)passp1 = Person()p1.printData() # 通过调用实例方法,验证在类的内部可直接访问私有属性
运行结果:
总结:将属性私有化后,就不可以在类的外部访问了,但内部使用不受任何影响
私有化属性可继承性:
class Person: # 父类def __init__(self):self.__name = '张三'passpassclass Teacher(Person): # 子类调用父类def test(self): # 子类中打印父类中的私有属性print(self.__name)t1 = Teacher() t1.test()
运行结果:
总结:父类的私有属性不可被子类继承
私有化方法
有些重要的方法,不允许外部调用或防止子类意外重写,可以把普通方法设置成私有化方法
语法规则
class Animal:def __showInfo(self): # 方法名前面加两个下划线print('这是动物类!')
使用私有化方法
案例:验证私有方法不可被外部直接访问且不可被继承
class Animal:def __showInfo(self):print('这是动物类!')passpassclass Bird(Animal):passb1 = Bird() b1.__showInfo()
运行结果:
案例:私有方法在类的内部可正常访问
class Animal:def __showInfo(self):print('这是动物类!')passdef printData(self):self.__showInfo()passclass Bird(Animal):passb1 = Bird() b1.printData()
运行结果:
总结:
- 私有方法不可被外部访问且不可被继承
- 私有方法在类内部可正常访问
命名规范
- 头单下划线:保护类变量(不常用) _name
- 头双下划线:私有属性【方法】 __name
- 头尾双下划线:魔术方法【系统所有】,不可自定义 _init_
- 尾单下划线: 避免变量名与关键字冲突时可使用 class_
Property属性
获取和修改私有属性的值
方法一:调用set方法
class Animal:__name = '张三'def getName(self):return self.__namedef setName(self, data):self.__name = dataa1 = Animal()
a1.setName('李四') # 通过调用set方法实现私有属性值的修改
print(a1.getName()) # 调用get方法实现私有属性值的获取
运行结果:
方法二:使用Property属性函数
Property属性函数可以通过点语法来获取、修改私有属性的值
class Animal:__name = '张三'def getName(self):return self.__namedef setName(self, data):self.__name = dataname = property(getName, setName) # property()方法有两个参数,分别为get、set的方法名a1 = Animal()
a1.name = '李四' # 点语法实现值的修改
print(a1.name) # 点语法实现值的获取
运行结果:
单例模式
实现整个系统中某个类的实例只创建一次
应用场景
网站登录(例如淘宝网,只允许一个账号同时浏览)
创建单例对象
class People(object):__instance = None # 私有属性用来存放首次创建的对象def __init__(self):print('对象创建成功!')def __new__(cls, *args, **kwargs):if not cls.__instance: # 如果 __instance 为None,说明该类还未曾创建过对象cls.__instance = object.__new__(cls) # 创建一个对象并用__instance记录下来return cls.__instanceelse: # 如果__instance不为None代表,该类已经创建过一个对象了,只需要直接返回之前创建的那个变量【__instance】return cls.__instancep1 = People()
p2 = People()
print(id(p1), id(p2))
运行结果:
错误与异常处理
引入
age = 10
print(name) # 未定义,运行会报错
print(age) # 已定义,理论上可以正常显示
上面代码中,未定义name而直接输出,程序会报错如下:
程序报错导致整个程序结束,因此age不能正常显示。
有没有办法可以输出错误内容并使程序正常运行?有,异常处理。
异常处理
try…except
age = 10 try:print(name) # 准备捕获异常的代码 except NameError as msg: # except后跟错误类型,as将结果重定向print('【{}】 异常'.format(msg)) print(age)
运行结果:
拓展:如果可能有多种错误类型怎么办?
try跟随多个except语句
l1 = ['hello', 1, True] try:print(l1[10]) except NameError as msg:print('【{}】 异常'.format(msg)) except IndexError as msg:print('【{}】 异常'.format(msg))
运行结果:
方法二:捕获所有异常(万能)
l1 = ['hello', 1, True] try:print(l1[10]) except Exception as msg:print(msg)
运行结果:
错误栈:
def A(data):return data / int(data)def B(data):return A(data) * 10def Func(data):B(data)Func(0)
分析:上面出现多个函数嵌套调用,每个函数中都需要写try…except?答案是:不需要
def A(data):return data / int(data)def B(data):return A(data) * 10def Func(data):try:B(data)except Exception as msg:print(msg)Func(0)
运行结果:
原理:
- 如果在函数中出现错误,则会将该错误返回到上一层,直至最顶层
- 如果错误出现在最顶层,则程序会结束
总结:合适位置添加try…except可以极大的减少代码量
else:
当try中未出现错误,会执行else语句
def Func(data):try:print(int(10 / int(data))) # try里面是可以输出内容的except Exception as msg:print(msg)else:print('程序无异常!')Func(5)
运行结果:
finally:
无论是否报错都会执行的语句
def Func(data):try:print(int(10 / int(data))) # try里面是可以输出内容的except Exception as msg:print(msg)finally:print('程序运行结束!')Func(5)
运行结果:
注意:虽然finally在这里显得很多余,但用其释放资源很方便。
自定义错误
直接或间接继承Exception类或者Error类
案例:当字符长度超过5时,抛出异常
class LenError(Exception): # 继承Exception类def __str__(self):return '您的字符长度超过所限制的5个字符!' # 自定义异常,msg内容来自__str__方法str = 'hello python!'
try:if len(str) > 5:raise LenError # raise用来抛出异常,不可用return(程序会停止运行)else:print(str)
except LenError as msg:print(msg)
运行结果:
动态属性和方法
动态属性
支持实例属性和类属性的添加
添加实例属性:
通过实例对象添加
class Student:def __init__(self, name, age):self.name = name # 初始方法定义实例变量self.age = agedef __str__(self):return '【{}】今年【{}】岁了。'.format(self.name, self.age)zyh = Student('张艳华', 20) zyh.weight = '101' # 动态添加实例属性 print(zyh.weight)
运行结果:
动态添加的属性仅对该实例对象有效,验证:
class Student:def __init__(self, name, age):self.name = name # 初始方法定义实例变量self.age = agedef __str__(self):return '【{}】今年【{}】岁了。'.format(self.name, self.age)zyh = Student('张艳华', 20) zyh.weight = '101' # 动态添加实例属性 wh = Student('王浩', 19) print(wh.weight)
运行结果:
添加类属性:
通过类对象添加
class Student:def __init__(self, name, age):self.name = name # 初始方法定义实例变量self.age = agezyh = Student('张艳华', 20) Student.weight = 101 # 动态添加类属性 print(zyh.weight)
运行结果:
动态方法
原理是把一个外部函数通过转换(types.MethodType())使其成为实例方法
添加实例方法:
通过实例对象添加,仅对该实例对象有效
import types # 导入用来转换的types包class Student:def __init__(self, name, age):self.name = name # 初始方法定义实例变量self.age = agedef func(self): # 自定义的一个外部函数,self不能忘记print('【{}】今年【{}】岁了!'.format(self.name, self.age))zyh = Student('张艳华', 20) zyh.printData = types.MethodType(func, zyh) # 实例对象.方法名=types.MethodType(外部函数名, 实例对象) zyh.printData() # 实例对象.方法名(调用定义的实例方法)
运行结果:
添加类方法和静态方法:
通过类对象实现
class Student:def __init__(self, name, age):self.name = name # 初始方法定义实例变量self.age = age@classmethod # 定义的外部方法,要满足类方法的条件:1、注明@classmethod 2、第一个参数默认是cls def func(cls):print('这是一个类方法!')Student.testFunc = func # 动态添加类方法(通过类对象实现的),(类对象.方法名=外部方法名) zyh = Student('张艳华', 20) zyh.testFunc() # 验证类方法是否添加成功(实例对象调用类方法)
运行结果:
注意:
- 静态方法同理(外部方法,要满足静态方法的条件)
- 类、静态方法不需要导入types包
_slots_
限制属性
添加属性(未使用slots方法):
class Student:passxm = Student() xm.name = '小明' # 动态添加实例属性 xm.age = 19 print(xm.name, xm.age)
运行结果:
限制属性添加(使用slots方法):
class Student: # 使用slots方法限制属性的添加,字符串类型的属性名放入元组中,逗号分隔__slots__ = ('name') # 仅允许添加一个名为name的属性passxm = Student() xm.name = '小明' # 动态添加实例属性 xm.age = 19 print(xm.name, xm.age)
运行结果:
节省内存
dict存放所有属性(消耗内存):
class Student:passxm = Student() xm.name = '小明' # 动态添加实例属性 xm.age = 19 print(xm.__dict__) # dict默认存放所有属性及其值
运行结果:
使用slots后dict会被删除(节省内存):
class Student:__slots__ = ('name', 'age')passxm = Student() xm.name = '小明' # 动态添加实例属性 xm.age = 19 print(xm.__dict__) # dict默认存放所有属性及其值
运行结果:
继承关系
案例1:父类限制属性(name,age),子类不限制,验证slots的限制不可继承
class Student: # 父类__slots__ = ('name', 'age') # 限制属性passclass Computer(Student): # 子类继承Student类passlm = Computer()
lm.sex = '男' # 动态定义实例属性(该属性不在父类slots限制中)
print(lm.sex) # 输出实例属性的内容
运行结果:
案例2:父类限制属性(name,age),子类限制属性(sex),验证slots的限制为其并集(父类+子类)
class Student: # 父类__slots__ = ('name', 'age') # 父类限制属性passclass Computer(Student): # 子类继承Student类__slots__ = ('sex') # 子类限制属性passlm = Computer()
lm.name = '李明' # 父类限制
lm.age = 18 # 父类限制
lm.sex = '男' # 子类限制
print('我叫【{}】,是个【{}】孩子,今年【{}】岁了!'.format(lm.name, lm.sex, lm.age)) # 输出实例属性的内容
运行结果:
总结:
- 若子类无slots方法,则不继承slots
- 若子类有slots方法,slots的限制为其并集(父类+子类)
不足之处,欢迎留言,会及时回复,及时更正!
创作不易,感谢支持!
AI学习 Day09 面向对象基础(下)相关推荐
- 第七章、 面向对象基础--下(续) 内部类、枚举、注解
文章目录 内容 学习目标 第七章 面向对象基础--下(续) 7.7 内部类 7.7.1 概述 7.7.1 非静态成员内部类 练习1:语法练习题 练习2:简单面试题 练习题3:高难面试题 7.7.2 静 ...
- Java核心技术基础知识学习之面向对象(下)
文章目录 五.面向对象(下) 5.1 包装类 5.2 处理对象 5.2.1 打印对象 5.2.2 ==和equals方法 5.3 类成员 5.3.1 理解类成员 5.3.2 单例类 5.4 final ...
- Python学习:面向对象基础练习——士兵突击(代码演示) 及 身份运算符
1.面向对象封装案例II--士兵突击 目标 士兵突击案例 身份运算符 封装 封装 是面向对象编程的一大特点 面向对象编程的 第一步 -- 将 属性 和 方法 封装 到一个抽象的 类 中 外界 使用 类 ...
- 千锋学习day09面向对象
面向对象 面向对象 面向对象思想(Object Oriented Programming )OOP: 一切客观存在的事物都是对象,万物皆对象 任何对象,一定具有自己的特征和行为 对象: 特征:称为属性 ...
- 个人python学习-Day7面向对象基础(上)
一.面向对象介绍 1.概述 面向过程:根据业务逻辑从上到下写代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象编程:将数据与函数绑定到一起,进行封装,这样能够更快速的 ...
- 面向对象基础任务训练分享
今天学习了面向对象基础,下面分享我的作业,请大家批评指正. 面向对象基础任务 任务1 任务2 任务3 今天学习了面向对象基础,下面分享我的作业. 任务1 编写 Car 类,属性有品牌(brand)和颜 ...
- Java基础学习——第六章 面向对象编程(下)
Java基础学习--第六章 面向对象编程(下) 一.关键词:static 1. static关键字的引入 当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new ...
- 【AI白身境】深度学习必备图像基础
文章首发于微信公众号<有三AI> [AI白身境]深度学习必备图像基础 今天是新专栏<AI白身境>的第四篇,所谓白身,就是什么都不会,还没有进入角色. 我们已经说了linux基础 ...
- 《疯狂Java讲义》学习笔记 第六章 面向对象(下)
<疯狂Java讲义>学习笔记 第六章 面向对象(下) 6.1包装类 基本数据类型 包装类 byte Byte short Short int Integer long Long char ...
- Python零基础速成班-第10讲-Python面向对象编程(下),Property属性、特殊方法、设计模式、链表应用
Python零基础速成班-第10讲-Python面向对象编程(下),Property属性.特殊方法.设计模式.链表应用 学习目标 面向对象编程 接上一讲:Property属性.特殊方法.设计模式 面向 ...
最新文章
- Android深度探索(卷1)HAL与驱动开发 第四章 源代码的下载和编译 读书笔记
- 嵌入式linux系统,给WIFI模块增加一个开关
- 数据结构实验之图论一:基于邻接矩阵的广度优先搜索遍历(BFS)
- 云计算具有什么平台_漫话:什么是云计算?
- Windows 10的下一个更新将在您观看视频时隐藏通知
- vs2005 vc++ 生成非托管的 不需要.net运行环境的exe程序方法
- 普通人有必要也学个人品牌吗?
- 21.docker logs
- 洛谷P5170 【模板】类欧几里得算法(数论)
- Jvisualvm监控远程SpringBoot项目
- fd开发website小技巧
- 编程英语(单词有音标)
- [mac]添加系统自带辞典或下载的词典包
- 小白声纹识别(说话人识别)探索
- 【python办公自动化(8)】批量处理调整Excel内容字体、对齐方式、边框、填充、合并与取消合并、行高及列宽(目标数据的筛选与标记)
- 高数_第5章常微分方程__一阶微分方程
- Redux 的基本使用
- RIP协议;OSPF协议;BGP协议
- laravel-admin 批量操作
- 马来西亚央行_马来西亚-第-1天总结