python 之 面向对象基础(组合和封装)
7.4 组合
解决类与类之间代码冗余问题有两种解决方案:
1、继承:描述的是类与类之间,什么是什么的关系
2、组合:描述的是类与类之间的关系,是一种什么有什么的关系
一个类产生的对象,该对象拥有一个属性,这个属性的值是来自于另外一个类的对象
class Date:
def __init__(self,year,mon,day):
self.year = year
self.mon = mon
self.day = day
def tell_birth(self):
print('出生年月日<%s-%s-%s>' % (self.year, self.mon, self.day))
class OldboyPeople:
school = 'oldboy'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex class OldboyTeacher(OldboyPeople):
def __init__(self,name,age,sex,level,salary):
super().__init__(name,age,sex) #重用父类功能
self.level=level
self.salary=salary
def change_score(self):
print('teacher %s is changing score' %self.name)
class Oldboystudent(OldboyPeople):
def __init__(self,name,age,sex,course,):
super().__init__(name,age,sex,) #重用父类功能
self.course=course
def choose(self):
print('student %s choose course' %self.name)
tea1=OldboyTeacher('egon',18,'male',9,3.1) #创建老师类的对象tea1
date_obj=Date(2000,1,1) #创建Date类的对象date_obj
date_obj.tell_birth() #date_obj可以调用绑定方法tell_birth
tea1.birth=date_obj #tea1的birth属性来自于Date类的一个对象date_obj
tea1.birth.tell_birth() #tea1的birth属性可以调用tell_birth属性
stu1=Oldboystudent('张三',16,'male','linux')
stu1.birth=Date(2002,3,3)
stu1.birth.tell_birth()
stu1.choose() #使用stu1将两个类联系起来
7.5 封装
什么是封装: 装就是把一堆属性存起来,封的概念就把这些属性给隐藏起来,其实这种隐藏只是一种语法上的变形,对外不对内
注意:
为一个属性名加__开头(注意不要加__结尾),会在类定义阶段将属性名统一变形:_自己的类名__属性名
class Foo:
x=1
__x=1111 #_Foo__x=1111
def __init__(self,y):
self.__y=y #self._Foo__y=y
def __f1(self): #_Foo__f1
print('Foo.f1')
def get_y(self):
print(self.__y) # print(self._Foo__y)
obj=Foo(22222)
print(obj.x) # 1
print(obj.__x) # 报错
print(obj._Foo__x) #
obj.__f1() #报错
obj._Foo__f1() # Foo.f1
print(obj.y) #报错
print(obj.__y) #报错
print(obj._Foo__y) #
obj.get_y() # 22222 明确地区分内外,对外是隐藏的,对内是开放的
这种语法意义上变形,只在类定义阶段发生一次,类定义之后,新增的__开头的属性都没有变形的效果
Foo.__aaa=1
print(obj.__aaa) # 1
如果父类不想让子类覆盖自己的方法,可以在方法名前加__开头
class Foo:
def __f1(self): #_Foo__f1
print('Foo.f1')
def f2(self):
print('Foo.f2')
self.__f1() #obj._Foo__f1()
class Bar(Foo):
def __f1(self): #_Bar__f1
print("Bar.f1")
obj=Bar()
obj.f2() # Foo.f2 Foo.f1
7.51 封装的作用
封装数据属性的目的:
把数据属性封装起来,然后需要开辟接口给类外部的使用者使用,好处是我们可以在接口之上添加控制逻辑,从而严格空间访问者对属性的操作
class People:
def __init__(self,name):
self.__name=name
def tell_name(self):
# 添加逻辑
return self.__name obj=People('egon')
#obj.__name
obj.tell_name()
封装函数属性的目的:为了隔离复杂度
class ATM:
def __card(self):
print('插卡')
def __auth(self):
print('用户认证')
def __input(self):
print('输入取款金额')
def __print_bill(self):
print('打印账单')
def __take_money(self):
print('取款')
def withdraw(self):
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
obj=ATM()
obj.withdraw()
7.52 封装之property
用来将类内的函数伪装成一个数据属性
例:
首先需要明确 : bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能 都会立即计算一个值
class People:
def __init__(self,name,weight,height):
self.name=name
self.weight=weight
self.height=height
@property #于是我们需要为bmi这个函数添加装饰器,将其伪装成一个数据属性
def bmi(self):
return self.weight / (self.height * self.height) egon=People('egon',75,1.80)
yl=People('yangli',85,1.74)
# print(egon.bmi())
# print(yl.bmi())
print(egon.bmi) # 21.604938271604937,调用egon.bmi本质就是触发函数bmi的执行,从而拿到其返回值
print(yl.bmi) # 把功能伪装成一个属性
@name.setter 和 @name.deleter
# egon.bmi=123
# egon.bmi背后对应的是一个函数,所以不能赋值
class People:
def __init__(self,name):
self.__name=name
@property
def name(self):
# 添加逻辑
return self.__name
@name.setter
def name(self,x):
# 添加逻辑
self.__name=x
@name.deleter
def name(self):
# 添加逻辑
del self.__name
obj=People('egon')
print(obj.name) # egon
# 修改
obj.name='EGON' # 现在可以赋值
print(obj.name) # EGON
del obj.name # 删除
obj.name # 报错
python 之 面向对象基础(组合和封装)的更多相关文章
- python开发面向对象基础:封装
一,封装 [封装] 隐藏对象的属性和实现细节,仅对外提供公共访问方式. [好处] 1. 将变化隔离: 2. 便于使用: 3. 提高复用性: 4. 提高安全性: [封装原则] 1. 将不需要对外提供的内 ...
- Java第三次作业——面向对象基础(封装)
Java第三次作业--面向对象基础(封装) (一)学习总结 1.什么是面向对象的封装性,Java中是如何实现封装性的?试举例说明. 封装性 封装性是面向对象的方法所应遵循的一个重要原则,它有两个含义: ...
- day020|python之面向对象基础2
面向对象基础2 目录 面向对象基础2 7 对象与类型 7.1 类即类型 7.1.1 变量的三个指标 7.1.2 变量类型 7.2 list.append()方法原理 8 对象的高度整合 8.1 通过面 ...
- Python全栈--9 __import__ 反射和面向对象基础 self 封装 继承(多继承的顺序) 多态
一.反射 python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员.获取成员.设置成员.删 ...
- python基础-9__import__ 反射和面向对象基础 self 封装 继承(多继承顺序) 多态
一 反射 python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员.获取成员.设置成员.删 ...
- PYTHON开发--面向对象基础入门
面向对象 一:面向对象初级 1.思考:首先在python中,以前我们以前用到的几乎都是函数式编程,但是有时候函数式编程其中代码重复利用率太高,我们往往会把这些重复代码写进一个函数日后去调用,所以呢,今 ...
- PYTHON开发--面向对象基础二
一.成员修饰符 共有成员 私有成员, __字段名 - 无法直接访问,只能间接访问 1. 私有成员 1.1 普通方法种的私有成员 class Foo: def __init__(self, n ...
- python开发面向对象基础:接口类&抽象类&多态&钻石继承
一,接口类 继承有两种用途: 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实 ...
- Python:面向对象基础
基本理论 什么是对象 万物皆对象 对象是具体的事物 拥有属性.行为 把许多零散的东西,封装成为一个整体 Python中一切东西都是对象,Python是一门特别彻底的面向对象编程语言(OOP) 其他编程 ...
随机推荐
- Git的使用(3) —— 远程版本库的操作(GitHub)
1. 配置SSH (1) GitHub 登陆GitHub后,点击右上角头像,选择 Setting . 在左面栏目中选择"SSH and GPG keys". 打开生成的SSH公钥文 ...
- 以前进行的程序安装创建了挂起的文件操作(SqlServer2000或SqlServer 2000 SP4补丁安装)
在安装SqlServer 2000或者SqlServer 2000 SP4补丁时常常会出现这样的提示,从而不能进行安装,即使重新启动了计算机,也还是会有同样的提示.在网上查了一下资料,原来是注册表里记 ...
- [C++] wchar_t关键字使用方法
char 是单字符类型,长度为一个字节 wchar_t 是宽字符类型,长度为两个字节,主要用在国际 Unicode 编码中 举例: #include<iostream> using nam ...
- [Windows] 输入字符间距变宽
今天在输入时,不会到误触到哪里,输入的字符间距变得很宽,如下图: 最后找到原因是不小心同时按下了 Shift+Space(空格),进入全角模式,就会导致输入的字符间距变宽 想要恢复,再按一次 shif ...
- Mysql 按年、季度、月、周查询统计
User表 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID', `username` varchar( ...
- 三大框架 之 SSH整合
目录 SSH整合 Spring整合web项目 在Servlet当中直接加载配置文件,获取对象 存在问题 解决方案 SSH整合 引入Jar包 引入配置文件 创建包结构 创建相关类 创建Customer业 ...
- 小福bbs-冲刺日志(第一天)
[小福bbs-冲刺日志(第一天)] 这个作业属于哪个课程 班级链接 这个作业要求在哪里 作业要求的链接 团队名称 小福bbs 这个作业的目标 开会,安排具体工作 作业的正文 小福bbs-冲刺日志(第一 ...
- R Shiny app | 交互式网页开发
网页开发,尤其是交互式动态网页的开发,是有一定门槛的,如果你有一定的R基础,又不想过深的接触PHP和MySQL,那R的shiny就是一个不错的选择. 现在R shiny配合R在统计分析上的优势,可以做 ...
- JVM 接口初始化规则
1.创建两个接口,MyParent5接口,MyChild5 接口继承自MyParent5接口 public class MyTest5 { public static void main(String ...
- RabbitMQ之Fanout交换器模式开发
Fanout模式,即广播模式,一个发送到交换机的消息会被转发到与该交换机绑定的所有队列上. 一.Provider 配置文件 spring.application.name=provider sprin ...