Python基于class()实现面向对象原理详解


Posted in Python onMarch 26, 2020

首先,类是一个集合,包含了数据,操作描述的一个抽象集合

你可以首先只把类当做一个容器来使用

class Cycle:
  def __init__(self,r):
    self.pi=3.14
    self.r=r
a=Cycle(4)
b=Cycle(7)

你看,我们定义了一个 Cycle 类,我们现在只是将它当做一个数据集合来用,我们利用其实例之间彼此数据隔离的特性来保证具体的实例数据彼此不污染。好了你现在想问,为什么我们要用数据集合来放数据

好了,我们来看看没有类之前我们会怎么样,假设我们现在要计算圆的面积

def square(r,pi):
  return pi * (r**2)
PI=3.14
a_r=4
a_square=square(a_r,PI)
b_r=7
b_square=square(b_r,PI)

看起来没有问题,好了,现在问题来了,假如,你现在要计算很多圆的面积,那么你是不是发现,不断的用变量命来隔离数据方式变得越来越脏了。而且你发现是不是有很多冗余的代码

好了我们这么改一改

class Cycle:
  def __init__(self,r):
    self.pi=3.14
    self.r=r

def square(value):
  if not isinstance(value,Cycle):
    raise ValueError("value muse be Cycle instace")
  value.square=value.pi * (value.r**2)

a=Cycle(4)
b=Cycle(7)

square(a)
square(b)

好了,你有没有觉得现在清晰了一点。

好了,现在我们现在还可以改一下

class Cycle:
  def __init__(self,r):
    self.pi=3.14
    self.r=r
  def square(self,value):
    return self.pi * (self.r**2)

好了,现在你可能迷惑了,我们为啥要把 square 函数放在类中?

好了,我现在要计算长方形,原型,梯形各种各样二维几何图形的面积,这样该怎么写???

你想了想我们之前说的将类作为数据容器,你想了想写了如下的代码

class Rectangle:
  def __init__(self,length,height):
    self.length=length
    self.height=height
class Cycle:
  def __init__(self,r):
    self.pi=3.14
    self.r=r
def rec_square(value):
  if not isinstance(value,Rectangle):
    raise ValueError("value muse be Rectangle instace")
  value.square=value.length * value.height
def cycle_square(value):
  if not isinstance(value,Cycle):
    raise ValueError("value muse be Cycle instace")
  value.square=value.pi * (value.r**2)

你想一想,这样是不是感觉如果计算需求越来越多,代码是不是还是会越来越脏?

如果我们将函数放在类里,并且用继承的特性,我们可以写出这样的代码

class Geometry:
  def get_square(self):
    raise NotImplementedError

class Rectangle(Geometry):
  def __init__(self,length,height):
    self.length=length
    self.height=height
  def get_square(self):
    return self.length*self.height

class Cycle(Geometry):
  def __init__(self,r):
    self.pi=3.14
    self.r=r
  def get_square(self):
    return self.pi * (self.r**2)

def square(value):
  if not isinstance(value,Geometry):
    raise ValueError("value muse be Geometry instace")
  value.square=value.get_square()

你看,我们现在只需要给用户暴露一个统一的接口,用户(用户也以是我们自己)不需要关心怎么样选择正确的函数,他只需要调用统一的 square 函数,就可以获取到具体的面积,是不是轻松很多了??

所以,类,它是对数据,操作的一种封装,这个封装的意义在于我们可以去更好的优化代码结构。

好了再举一个例子,我们可以用类来控制访问权限

class People:
  def __init__(self,website):
    self.__favorite_website="1024.com"
  def bad_or_not(self):
    return self.__favorite_website=="1024.com"

你看,我们用 private 变量,来确保外部没法直接访问一些敏感数据(实际上 Python 里 private 并不严格,hook 一下还是可以访问的)

好,在举一个例子

class People:
  def __init__(self,website):
    self.__favorite_website="1024.com"
  def bad_or_not(self):
    return self.__favorite_website=="1024.com"
  @property
  def favorite_website(self):
    return self.__favorite_website
  @favorite_website.setter
  def favorite_website(self,value):
    if value=="1024.com":
      raise ValueError("你不能去草榴,兄弟,你营养不足")
    self.__favorite_website=value

你看,我们现在很方便的实现在设置数据值的时候,对其过滤。

撤了这么多,回到你的问题

首先A君说的没毛病,但我想知道仅仅使用函数锤子,螺丝刀来完成一个项目比使用Class工厂+函数锤子来完成一个项目的效率会更低么?

理由是什么?大神在什么时候会考虑使用Class来提高代码的“执行效率”和代码的“可读性”。回归实际情况,我很多时候都是调用同一个函数/方法去输出某个结果。

至今还想不出为什么调用Class会更方便?(PS:本人大菜鸟,写了上千行代码了,但仍然搞不懂什么情况下需要用到Class类。也曾尝试在自己的代码中强行加入Class输出结果

但感觉不灵活,而且要写的代码明显多了也不便于理解。求大神举例,碾压我的无知!)。C君说大型项目不使用Class调用对象会累死,到底这个“累死”体现在哪里?

首先一个问题,我整个答案里所写的这些代码,不用面向对象这一套能不能实现?

很明显,能。

但是实现的干净么?个人觉得不干净。

项目规格上去后,我们如果按照传统的方式进行开发,务必要多重检查,确保自己不会手抖调用了错误的东西。而 OOP 这一套思想,其实就是通过利用合适的代码结构和封装,某种程度上来讲是减少我们犯错的可能。

同时,现在开发基本都不是一个人的单打独斗,你写的代码可能会被其余人使用与维护。我们有个前提,要假设使用维护你代码的人都是傻逼。我们要适当的封装代码,优化结构,让使用者尽可能的少犯错、

所以最后,无论是各个语言的变量命名规则也好,还是 OOP 这一套范式也好。其本质是在自由度与可读性可维护性之间的一种相对较优的妥协,这种妥协根本的目的就在于通过规范化的操作与封装,减少团队开发维护的成本,优化开发体验。

另外,关于开发这一套还有个老生常谈的问题过度封装。我个人的观点是在你知道什么是 过度封装 之前,你没必要考虑这个问题,按照教科书和开源代码里的结构,去不断封装优化你的代码。

面向对象 更容易使用 ,缺点就是 换一个开发人,难维护,很难理解前面人的思维,出了错不好找位置

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
对于Python的Django框架使用的一些实用建议
Apr 03 Python
Python线程的两种编程方式
Apr 14 Python
Python装饰器使用实例:验证参数合法性
Jun 24 Python
Python中标准模块importlib详解
Apr 16 Python
关于python的list相关知识(推荐)
Aug 30 Python
python 检查文件mime类型的方法
Dec 08 Python
python画图--输出指定像素点的颜色值方法
Jul 03 Python
jupyter notebook 添加kernel permission denied的操作
Apr 21 Python
使用python实现CGI环境搭建过程解析
Apr 28 Python
Python3 pywin32模块安装的详细步骤
May 26 Python
python能否java成为主流语言吗
Jun 22 Python
如何使用python-opencv批量生成带噪点噪线的数字验证码
Dec 21 Python
Python文件读写w+和r+区别解析
Mar 26 #Python
Python装饰器实现方法及应用场景详解
Mar 26 #Python
pycharm中导入模块错误时提示Try to run this command from the system terminal
Mar 26 #Python
Python多进程编程常用方法解析
Mar 26 #Python
简单了解python调用其他脚本方法实例
Mar 26 #Python
Python tornado上传文件的功能
Mar 26 #Python
Python Tornado批量上传图片并显示功能
Mar 26 #Python
You might like
实测在class的function中include的文件中非php的global全局环境
2013/07/15 PHP
PHP获取当前完整URL地址的函数
2014/12/21 PHP
PHP实现在线阅读PDF文件的方法
2015/06/17 PHP
PHP简单创建压缩图的方法
2016/08/24 PHP
js操作checkbox遇到的问题解决
2013/06/29 Javascript
如何使用JS获取IE上传文件路径(IE7,8)
2013/07/08 Javascript
js设置组合快捷键/tabindex功能的方法
2013/11/21 Javascript
jquery简单实现鼠标经过导航条改变背景图
2013/12/17 Javascript
Backbone.js 0.9.2 源码注释中文翻译版
2015/06/25 Javascript
详解获取jq ul第一个li定位的四种解决方案
2016/11/23 Javascript
使用Javascript判断浏览器终端设备(PC、IOS(iphone)、Android)
2017/01/04 Javascript
js实现交通灯效果
2017/01/13 Javascript
微信小程序 详解页面跳转与返回并回传数据
2017/02/13 Javascript
js实现动态增加文件域表单功能
2018/10/22 Javascript
微信小程序--特定区域滚动到顶部时固定的方法
2019/04/28 Javascript
小程序登录/注册页面设计的实现代码
2019/05/24 Javascript
解决vue自定义全局消息框组件问题
2019/11/22 Javascript
Python中的map()函数和reduce()函数的用法
2015/04/27 Python
python cumsum函数的具体使用
2019/07/29 Python
关于Python形参打包与解包小技巧分享
2019/08/24 Python
利用python实现周期财务统计可视化
2019/08/25 Python
Python中bisect的用法及示例详解
2020/07/20 Python
Python实现钉钉/企业微信自动打卡的示例代码
2021/02/02 Python
CSS3五个技巧给你的网站带来出色的效果
2009/04/02 HTML / CSS
施惠特软件测试面试题以及笔试题
2015/05/13 面试题
Java编程面试题
2016/04/04 面试题
超市后勤自我鉴定
2014/01/17 职场文书
探亲邀请信范文
2014/01/30 职场文书
临床医学专业求职信
2014/08/08 职场文书
2014年质检工作总结
2014/11/26 职场文书
2015年个人自我剖析材料
2014/12/29 职场文书
2015年世界无车日活动总结
2015/03/23 职场文书
python - timeit 时间模块
2021/04/06 Python
MySQL如何使用使用Xtrabackup进行备份和恢复
2021/06/21 MySQL
golang连接MySQl使用sqlx库
2022/04/14 Golang
Java获取字符串编码格式实现思路
2022/09/23 Java/Android