Python面向对象编程基础解析(二)
作者:张璨 发布时间:2023-11-16 01:53:23
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目录放一些重要的代码,比如重要的逻辑,类的定义等
来源:http://www.cnblogs.com/zhang-can/p/7142544.html


猜你喜欢
- 在之前的几篇文章中,介绍了业界中比较火爆的图片技术SVG(Scalable Vector Graphics),比如Iconfont(矢量图标
- 本文实例为大家分享了pygame实现雷电游戏开发代码,供大家参考,具体内容如下源代码:stars.py#-*- coding=utf-8 -
- 老婆大人让俺帮她通过Excel生成百人的准考证,她们学校打算来一次高考模拟。由于高考改革,每个学生的考试科目不一样,需要自动生成一下。我一个
- 一、配置webdriver下载谷歌浏览器驱动,并配置好import timeimport randomfrom PIL import Ima
- 本篇文章面向的读者: 已经基本掌握Go中的 协程(goroutine),通道(channel),互斥锁(sync.Mutex),读
- 在MySQL服务器启动时,它检查其命令行的操作,来查看它是否应该执行登录并打开相应的日志文件(如果应该的话)。可以让服务器生成两种主要类型的
- 前言最近又在重新学习编译原理了,其实两年前也复习过,当初是为了能实现通过 MySQL 的 DDL 生
- max() 方法返回其参数最大值:最接近正无穷大的值。语法以下是max()方法的语法:max( x, y, z, .... )参
- 目录1 键的类型,列表/字典不可以,其它都可以2 多个对象可当作键名,顺序不同时是不同的键3 结论【有误】:今天看别人代码时发现一个事,就是
- 1、灵活运用样式 熟悉网页设计的网友就知道,调用Style的方法很多,我们可以单击鼠标右键选择Custon Style来调用Style标准,
- js代码:window.alert = function(msg, callback) {var div = document.create
- 在实际应用中,经常会遇上这样的小需求:根据一段给定的数组,生成由这一段数组值构成的对称矩阵。例如,给定数组[1,2,3,4,5,6,7,8,
- 1、什么是GIL全局解释器锁GIL:Global Interpreter Lock,意思就是全局解释器锁,这个GIL并不是Python的特性
- 一、前言很多网站提供视频转GIF的功能,但要么收费要么有广告实际上我们通过python,几行代码就能够实现视频转gif二、教程1. 安装必备
- python爬虫中使用urli库可以使用opener"发送多个请求,这些请求是能共享处理cookie的,小编之前也提过python
- 本文实例讲述了Python编程修改MP3文件名称的方法。分享给大家供大家参考,具体如下:最近刚刚开始学习Python,顺便锻炼思维写的一个小
- 关于js中的offsetWidth、clientWidth、scrollWidth等一系列属性及其方法一直都傻傻分不清,这里就来总结一下这些
- 也就在前几天,南太平洋岛国汤加发生火山喷发,有专门的专家学者分析,这可能是30年来全球规模最大的一次海底火山喷发,它引发的海啸以及火山灰将对
- 在数据库中,字符型的数据是最多的,可以占到整个数据库的80%以上。为此正确处理字符型的数据,对于提高数据库的性能有很大的作用。在字符型数据中
- 【导语】:对自己写的冗长代码,想重构但又无思路?小编整理了系列介绍python代码重构优化的方法,助你一臂之力。编写干净的 Pythonic