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 14 Python
Python使用chardet判断字符编码
May 09 Python
python实现查找excel里某一列重复数据并且剔除后打印的方法
May 26 Python
tensorflow: variable的值与variable.read_value()的值区别详解
Jul 30 Python
在Python中合并字典模块ChainMap的隐藏坑【推荐】
Jun 27 Python
Java文件与类动手动脑实例详解
Nov 10 Python
python 函数嵌套及多函数共同运行知识点讲解
Mar 03 Python
Python面向对象程序设计之类和对象、实例变量、类变量用法分析
Mar 23 Python
Pytorch高阶OP操作where,gather原理
Apr 30 Python
使用 prometheus python 库编写自定义指标的方法(完整代码)
Jun 29 Python
Django项目在pycharm新建的步骤方法
Mar 02 Python
浅谈Python numpy创建空数组的问题
May 25 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
常见的四种POST 提交数据方式(小总结)
2015/10/08 PHP
让你的PHP7更快之Hugepage用法分析
2016/05/31 PHP
Laravel框架表单验证操作实例分析
2019/09/30 PHP
javascript 学习笔记(onchange等)
2010/11/14 Javascript
使用jQuery实现dropdownlist的联动效果(sharepoint 2007)
2011/03/30 Javascript
js判断undefined类型示例代码
2014/02/10 Javascript
jquery提交form表单时禁止重复提交的方法
2014/02/13 Javascript
JS常用字符串处理方法应用总结
2014/05/22 Javascript
原生javascript实现DIV拖拽并计算重复面积
2015/01/02 Javascript
javascript实现数组去重的多种方法
2016/03/14 Javascript
javascript中利用柯里化函数实现bind方法【推荐】
2016/04/29 Javascript
jquery按回车键实现表单提交的简单实例
2016/05/25 Javascript
浅谈react受控组件与非受控组件(小结)
2018/02/09 Javascript
解决layui 复选框等内置控件不显示的问题
2018/08/14 Javascript
Angular4 Select选择改变事件的方法
2018/10/09 Javascript
简单学习5种处理Vue.js异常的方法
2019/06/17 Javascript
vue实现登录功能
2020/12/31 Vue.js
[05:23]DOTA2-DPC中国联赛2月1日Recap集锦
2021/03/11 DOTA
python实现list由于numpy array的转换
2018/04/04 Python
Python中出现IndentationError:unindent does not match any outer indentation level错误的解决方法
2020/04/18 Python
Python面向对象之继承和多态用法分析
2019/06/08 Python
Django 再谈一谈json序列化
2020/03/16 Python
如何真正的了解python装饰器
2020/08/14 Python
HTML5本地存储之Web Storage应用介绍
2013/01/06 HTML / CSS
全球最大的在线旅游公司:Expedia
2017/11/16 全球购物
自主招生自荐信范文
2013/12/04 职场文书
大学生个人简历中的自我评价
2013/12/27 职场文书
餐饮收银员岗位职责
2014/02/07 职场文书
母校寄语大全
2014/04/10 职场文书
淘宝客服专员岗位职责
2014/04/11 职场文书
2015年毕业生自我鉴定模板
2014/09/19 职场文书
优秀高中学生评语
2014/12/30 职场文书
病危通知单
2015/04/17 职场文书
2016教师节问候语
2015/11/10 职场文书
Python基础之hashlib模块详解
2021/05/06 Python
mysql查看表结构的三种方法总结
2022/07/07 MySQL