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 相关文章推荐
使用python绘制人人网好友关系图示例
Apr 01 Python
Django框架中处理URLconf中特定的URL的方法
Jul 20 Python
python socket多线程通讯实例分析(聊天室)
Apr 06 Python
Python探索之创建二叉树
Oct 25 Python
对python中for、if、while的区别与比较方法
Jun 25 Python
Python统计python文件中代码,注释及空白对应的行数示例【测试可用】
Jul 25 Python
对Python使用mfcc的两种方式详解
Jan 09 Python
20行python代码实现人脸识别
May 05 Python
树莓派+摄像头实现对移动物体的检测
Jun 22 Python
python简单区块链模拟详解
Jul 03 Python
python统计文章中单词出现次数实例
Feb 27 Python
Pytorch实现WGAN用于动漫头像生成
Mar 04 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
基于Codeigniter框架实现的student信息系统站点动态发布功能详解
2017/03/23 PHP
php curl优化下载微信头像的方法总结
2018/09/07 PHP
TNC vs BOOM BO3 第三场2.13
2021/03/10 DOTA
小议Javascript中的this指针
2010/03/18 Javascript
combox改进版 页面原型参考dojo的,比网上jQuery的那些combox功能强,代码更小
2010/04/15 Javascript
JQUERY设置IFRAME的SRC值的代码
2010/11/30 Javascript
为超链接加上disabled后的故事
2010/12/10 Javascript
js读取配置文件自写
2014/02/11 Javascript
自己封装的常用javascript函数分享
2015/01/07 Javascript
JavaScript检测上传文件大小的方法
2015/07/22 Javascript
详解webpack分包及异步加载套路
2017/06/29 Javascript
详解vue+css3做交互特效的方法
2017/11/20 Javascript
js如何找出字符串中的最长回文串
2018/06/04 Javascript
jQuery 常用特效实例小结【显示与隐藏、淡入淡出、滑动、动画等】
2020/05/19 jQuery
[52:14]VG vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
Python isinstance判断对象类型
2008/09/06 Python
在centos7中分布式部署pyspider
2017/05/03 Python
python中的随机函数random的用法示例
2018/01/27 Python
pandas数据清洗,排序,索引设置,数据选取方法
2018/05/18 Python
详解django自定义中间件处理
2018/11/21 Python
使用python从三个角度解决josephus问题的方法
2020/03/27 Python
python的数学算法函数及公式用法
2020/11/18 Python
英国现代市场:ARKET
2019/04/10 全球购物
Pureology官网:为染色头发打造最好的产品
2019/09/13 全球购物
Ajax主要包含了哪些技术
2014/06/12 面试题
项目专员岗位职责
2013/12/04 职场文书
餐饮业经理竞聘演讲稿
2014/01/14 职场文书
美术教学感言
2014/02/22 职场文书
毕业生就业意向书
2014/04/01 职场文书
幼儿园见习报告范文
2014/10/30 职场文书
家长对孩子的寄语
2015/02/26 职场文书
放牛班的春天观后感
2015/06/01 职场文书
学习杨善洲同志先进事迹心得体会
2016/01/23 职场文书
Nginx反爬虫策略,防止UA抓取网站
2021/03/31 Servers
MySQL的join buffer原理
2021/04/29 MySQL
python可视化大屏库big_screen示例详解
2021/11/23 Python