Python面向对象编程基础解析(二)


Posted in Python onOctober 26, 2017

Python最近挺火呀,比鹿晗薛之谦还要火,当然是在程序员之间。下面我们看看有关Python的相关内容。

上一篇文章我们已经介绍了部分Python面向对象编程基础的知识,大家可以参阅:Python面向对象编程基础解析(一),接下来,我们看看另一篇。

封装

1.为什么要封装?

封装就是要把数据属性和方法的具体实现细节隐藏起来,只提供一个接口。封装可以不用关心对象是如何构建的,其实在面向对象中,封装其实是最考验水平的

2.封装包括数据的封装和函数的封装,数据的封装是为了保护隐私,函数的封装是为了隔离复杂度

3.数据的封装就是在属性前面加一个__

class People:
 def __init__(self,name,age,salary):
  self.name=name
  self.age=age
  self.__salary=salary
p=People('zhang',19,100000)
print(p.name)#zhang
print(p.age)#19
print(p.__salary)#AttributeError: 'People' object has no attribute '__salary'

咦,报错了,让我们打开对象的名称空间,看看发生了什么

print(p.__dict__)#{'name': 'zhang', 'age': 19, '_People__salary': 100000}

哦,原来python把__salary变形成了_People__salary,再来一遍

print(p._People__salary)#100000

所以,Python中并没有绝对的隐藏,只要你知道了上面这个,就无所谓隐藏了
这些变形操作,只在类的定义阶段或者对象定义(实例化阶段)阶段发生

虽然在外部无法直接访问加了__的属性,但是在类内部可以访问到,可以这么理解,在定义阶段,只要遇到__开头的,Python解释器自动识别为_类名__属性,所以在类内部是可以访问到的,这样的话,我们就可以搞一点小事情了

先来看这个

class A:
 def foo(self):
  print('from A foo')
  self.bar()
 def bar(self):
  print('from A bar')
class B(A):
 def bar(self):
  print('from B bar')
b=B()
b.foo()  #from A foo


#from B bar 别想多了,调用函数时别看定义位置,要看调用位置

如果就是想调用父类的bar()函数呢?该怎么做

class A:
 def foo(self):
  print('from A foo')
  self.__bar()
 def __bar(self):
  print('from A bar')
class B(A):
 def __bar(self):
  print('from B bar')
b=B()
b.foo() #from A foo
  #from A bar有没有感受到编程的美妙

4.封装的应用

1)不让外界看到我们的数据属性是怎么定义的,只能通过我们提供的接口,看到我们允许外界看到的内容

class People:
 def __init__(self,name,age,height,weight,hobby):
  self.__name=name
  self.__age=age
  self.__height=height
  self.__weight=weight
  self._hobby=hobby
 def tell_info(self):
  print('''
  name:%s
  age:%s
  height:%s
  weeight:%s
  '''%(self.__name,self.__age,
    self.__height,self.__weight))
p=People('zhang',18,1.90,75,'read')
p.tell_info()

2)更常用的场景是,我们可以限制数据的类型,添加自己的逻辑以后再封装好给用户

def tell_name(self):
  print(self.__name)
 #修改名字
 def set_name(self,new):
  if not isinstance(new,str):
   raise TypeError('名字必须是字符串类型')
  self.__name=new

5.看我们上面的操作,用户查看名字的时候还得p.tell_name(),本来是个数据属性,却被我们搞得变成了一个函数,怎么伪装一下呢,就可以用到property这个装饰器了

class People:
 def __init__(self,name,age,height,weight,hobby):
  self.__name=name
  self.__age=age
  self.__height=height
  self.__weight=weight
  self._hobby=hobby
 @property
 def name(self):
  return self.__name
p=People('zhang',18,1.90,75,'read')
print(p.name)#zhang

数据属性还应该有修改,删除操作

@property
 def name(self):
  return self.__name
 #name已经被property修饰过,就有setter和deleter
 @name.setter
 def name(self,new):
  if not isinstance(new,str):
   raise TypeError('名字必须是字符串类型')
  self.__name=new
 @name.deleter
 def name(self):
  del self.__name
p = People('zhang', 18, 1.90, 75, 'read')
print(p.name)#zhang
p.name='can' #修改
print(p.name)#can
del p.name #删除
print(p.name)#AttributeError: 'People' object has no attribute '_People__name'

1.多态

多态的概念虽然现在才说,但是我们一直在用。多态就是多种形态的意思,动物都猫,狗,猪等等,这些都是动物的多种形态。

反映在Python中,多态就意味着就算不知道变量所引用的对象类型是什么,也能对它进行操作。比如序列类型有计算长度的方法len(),那我们拿到一个序列类型x,我们不需要知道x是什么类型,只需要知道它是序列类型,那我们就可以用len(x)的方法计算x的长度。这就是多态性,Python本身就是多态的

当然我们学过一个内置函数isinstance(),可以用它来判断数据类型,但是这可不符合多态优美的特性

2.绑定方法与非绑定方法

类里面定义的函数有两种,绑定方法和非绑定方法

1)绑定方法

绑定方法又分为绑定给类的方法和绑定给对象用的方法。

凡是定义在类中,且没有被任何装饰器修饰的方法,都是绑定给对象用的方法。

特点是obj.func()会自动把obj当作第一个参数传入,因为func的逻辑就是要处理obj

在类中定义的被classmethod装饰器修饰的方法,就是绑定给类的方法

特点是cls.func()会自动把类cls当作第一个参数传入,因为func的逻辑是处理cls,就算是对象调用这个函数,也是把类当成第一个参数传入

class People:
 def __init__(self,name):
  self.name=name
 def bar(self):
  print('----->',self.name)
 @classmethod
 def func(cls):
  print(cls)
p1=People('zhang')
p1.func() #<class '__main__.People'>
People.func()#<class '__main__.People'>

2)非绑定方法

还有一种方法是既不绑定给类,也不绑定给对象的,叫做非绑定方法

用staticmethod装饰器装饰

#文件名:pickle_test
import hashlib
import time
import pickle
import os
student_path=r'C:\Users\Administrator\PycharmProjects\test\student'
class People:
 def __init__(self,name,sex,user_id):
  self.name=name
  self.sex=sex
  self.user_id=user_id
  self.id = self.create_id()
 def tell_info(self):
  print('''
  --------%s info--------
  id:%s
  name:%s
  sex:%s
  user_id:%s
  ''' %(self.name,self.id,self.name,self.sex,self.user_id))
 def create_id(self):
  m=hashlib.md5()
  m.update(self.name.encode('utf-8'))
  m.update(self.sex.encode('utf-8'))
  m.update(str(self.user_id).encode('utf-8'))
  return m.hexdigest()
 def save(self):
  with open(self.id,'wb') as f:
   pickle.dump(self,f)
 @staticmethod #非绑定方法,就是一个函数,就是一个工具而已,不需要类,也不需对象
 def get_all():
  res = os.listdir(student_path)
  for item in res:
   file_path=r'%s\%s' %(student_path,item)
   with open(file_path,'rb') as f:
    obj=pickle.load(f)
    obj.tell_info()
#反序列化.py
from pickle_test import People
p=People('zhang','male',123123123)
p.get_all()

3.软件开发规范

在真正的软件开发过程中,并不是把所有代码写在一个文件中的,可以想象一下,一个小程序大概有10000行代码,都写在一个文件中的话,你还干这行吗?

正确的方式应该是把程序拆成一个一个模块。比如常用的bin目录放可执行文件,conf目录放配置文件
db目录放数据,log目录放日志文件,lib目录放库,src目录放一些重要的代码,比如重要的逻辑,类的定义等

总结

以上就是本文关于Python面向对象编程基础解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:Python探索之ModelForm代码详解、python中requests爬去网页内容出现乱码问题解决方法介绍等,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

Python 相关文章推荐
python3图片转换二进制存入mysql
Dec 06 Python
使用python编写android截屏脚本双击运行即可
Jul 21 Python
在Linux上安装Python的Flask框架和创建第一个app实例的教程
Mar 30 Python
简介Python中用于处理字符串的center()方法
May 18 Python
小米5s微信跳一跳小程序python源码
Jan 08 Python
python执行系统命令后获取返回值的几种方式集合
May 12 Python
对python 操作solr索引数据的实例详解
Dec 07 Python
Python二进制文件读取并转换为浮点数详解
Jun 25 Python
Python对接六大主流数据库(只需三步)
Jul 31 Python
python 实现在shell窗口中编写print不向屏幕输出
Feb 19 Python
appium+python adb常用命令分享
Mar 06 Python
Python爬虫入门案例之回车桌面壁纸网美女图片采集
Oct 16 Python
Python面向对象编程基础解析(一)
Oct 26 #Python
获取Django项目的全部url方法详解
Oct 26 #Python
Python探索之ModelForm代码详解
Oct 26 #Python
启动targetcli时遇到错误解决办法
Oct 26 #Python
Mac中Python 3环境下安装scrapy的方法教程
Oct 26 #Python
python实现分页效果
Oct 25 #Python
python+pyqt实现12306图片验证效果
Oct 25 #Python
You might like
PHP安全性漫谈
2012/06/28 PHP
PHP中4个加速、缓存扩展的区别和选用建议
2014/03/12 PHP
thinkphp学习笔记之多表查询
2014/07/28 PHP
去掉destoon资讯内容页keywords关键字自带的文章标题的方法
2014/08/21 PHP
ThinkPHP中pathinfo的访问模式、路径访问模式及URL重写总结
2014/08/23 PHP
如何用javascript去掉字符串里的所有空格
2007/02/08 Javascript
window.location.href IE下跳转失效的解决方法
2014/03/27 Javascript
javascript中返回顶部按钮的实现
2015/05/05 Javascript
浅谈Javascript数组(推荐)
2016/05/17 Javascript
JavaScript中0和&quot;&quot;比较引发的问题
2016/05/26 Javascript
jQuery实现拖拽页面元素并将其保存到cookie的方法
2016/06/12 Javascript
BootStrap 智能表单实战系列(五) 表单依赖插件处理
2016/06/13 Javascript
canvas实现手机端用来上传用户头像的代码
2016/10/20 Javascript
JS实现超简单的汉字转拼音功能示例
2016/12/22 Javascript
Mac下使用charles遇到的问题以及解决办法
2017/01/10 Javascript
bootstrap表格内容过长时用省略号表示的解决方法
2017/11/21 Javascript
elementUI 动态生成几行几列的方法示例
2019/07/11 Javascript
Vue 实现登录界面验证码功能
2020/01/03 Javascript
jQuery实现手风琴效果(蒙版)
2020/01/11 jQuery
[15:57]教你分分钟做大人:斧王
2014/10/30 DOTA
Python实现过滤单个Android程序日志脚本分享
2015/01/16 Python
python实现人工智能Ai抠图功能
2019/09/05 Python
python实现跨excel sheet复制代码实例
2020/03/03 Python
numpy中生成随机数的几种常用函数(小结)
2020/08/18 Python
python 图像增强算法实现详解
2021/01/24 Python
StubHub澳大利亚:购买或出售您的门票
2019/08/01 全球购物
PHP引擎php.ini参数优化深入讲解
2021/03/24 PHP
党章学习思想汇报
2014/01/14 职场文书
《口技》教学反思
2014/02/21 职场文书
个人授权委托书范本
2014/04/03 职场文书
小学家长学校培训材料
2014/08/24 职场文书
交通事故和解协议书
2015/01/27 职场文书
物业工程部岗位职责
2015/02/11 职场文书
隐形的翅膀观后感
2015/06/10 职场文书
董事长秘书工作总结
2015/08/14 职场文书
2016国庆节67周年寄语
2015/12/07 职场文书