Py-多态,封装,反射,描述符,包装标准类型,面向对象进阶

时间:2021-10-09 22:58:31

多态:

对象可以通过他们共同的属性和动作来访问,而不需要考虑他们的类
多态是继承的应用

class H2o:
def __init__(self,temp):
self.temp=temp
def htype(self):
if self.temp<=0:
print('结冰')
if self.temp>0 and self.temp<60:
print('化成水')
if self.temp>=60:
print('水蒸气')
class bing(H2o):
pass
class shui(H2o):
pass
class qi(H2o):
pass
ice=bing(0)
water=shui(30)
gas=qi(80)
ice.htype() #ice,water,gas不同的类但是能调用相同的动作,方法
water.htype()
gas.htype()
#可以封装成函数来调用这些相同的方法
def func(obj):
obj.htype()
#这要属于H20这个父类的都能用func
func(ice)

封装:

是要明确内外,外部调用的时候看不见它,自己里面使用的时候才能看见

class H2o:
_ab=123
__bc=234
def __init__(self,temp):
print(H2o.__bc) #内部可以直接调用,外部不行
self.temp=temp
def htype(self):
if self.temp<=0:
print('结冰')
if self.temp>0 and self.temp<60:
print('化成水')
if self.temp>=60:
print('水蒸气')
alex=H2o(10)
其他文件import这个py文件调用时
看见这些带_的都是封装的,希望外部不访问的
如果硬要访问的话可以通过
from 封装 import H2o
water=H2o(30)
print(water._ab) #单斜杠的封装可以这样调用
print(water._H2o__bc) #这个双斜杠的封装可以这样调用
#双斜杠调用的格式_类名__双斜杠封装名

正常访问时在函数内部写非封装接口(里面包含着封装内容)来给别人调用

自省,反射

反射又称为自省,是指程序可以访问检测修改自身的一种能力

1.hasattr(对象,字符串):用于查对象或者类里面是否有某个字符串的属性

class Blackmedium:
feture='ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_hourse(self):
print('%s 正在卖房' %self.name)
def rent_hourse(self):
print('%s 正在租房子' %self.name)
b1=Blackmedium('广域网','撒旦')
print(hasattr(b1,'feture'))
print(hasattr(b1,'sell_hourse'))

2.getattr:用于查对象或者类里面是否有某个字符串的值或者函数的运行地址

class Blackmedium:
feture='ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_hourse(self):
print('%s 正在卖房' %self.name)
def rent_hourse(self):
print('%s 正在租房子' %self.name)
b1=Blackmedium('广域网','撒旦')
print(getattr(b1,'feture'))
print(getattr(b1,'sell_hourse'))

3.setattr设置和修改对象或者类属性

class Blackmedium:
feture='ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_hourse(self):
print('%s 正在卖房' %self.name)
def rent_hourse(self):
print('%s 正在租房子' %self.name)
b1=Blackmedium('广域网','撒旦')
#给对象设置属性
setattr(b1,'sb',123123)
print(b1.sb)

反射:

一个人写了一段代码,但是没有写完。另一个人现在想写,利用反射可以
那个人现在改写了,但是原来的人回来时还能重置回自己原来的继续写

class Blackmedium:
feture='ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
b1=Blackmedium('广域网','撒旦')
if hasattr(b1,'put'):
func_get=getattr(b1,'put')
func_get()
else:
print('运行其他的luoji')
高级的导入方法__import__,传字符串
该py文件的同一级有一个CT1文件夹,里面有一个login.py
import importlib
m=importlib.import_module('CT1.login')
print(m)

描述符

类的内置attr属性,描述符基于__getattr__,__setattr__,__delattr__这三个
描述符:描述符就是一个类,只不过它定义了另一个类中属性的访问方式。
换句话说,一个类可以将属性管理全权委托给描述符类。
要遵循优先级

类属性>数据描述符>实例属性>非数据描述符>找不到的属性触发__getattr__

class Blackmedium:
feture='ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def __getattr__(self,item):
print('执行')
b1=Blackmedium('广域网','撒旦')
print(b1.feture)
print(getattr(b1,'feture')) #使用来查找对象里的字符串的属性值,有就返回属性值
print(getattr(b1,'dsadadsad'))#没有就返回none
b1.sssssssb #当调用的对象里面没有该属性时,进行__getattr__里面的内容

删除属性delattr,使用del时会触发__delattr__

class Blackmedium:
feture='ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def __delattr__(self,item):
print('删除')
b1=Blackmedium('广域网','撒旦')
del Blackmedium.feture
print(b1.__dict__)
print(Blackmedium.__dict__) #可以看见类下面的这个属性被删除了

修改属性setattr,使用setattr时会触发__setattr__

class Blackmedium:
feture='ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def __setattr__(self,key,value):
print('添加和修改完成')
self.__dict__[key]=value
b1=Blackmedium('广域网','撒旦')
print(b1.__dict__)
b1.sb='ni'
print(b1.__dict__)

包:

大型项目中往往需要分模块,功能相似的模块可以用包组成层次组织结构,方便维护
目录
\顶层文件夹
    __init__.py
    \subpackage1
        __init__.py
        mod1.py
        mod2.py
    \subpackage2
        __init__.py
        mod3.py
程序
import subpackage1.mod1.py

包装标准类型

1.包装list,继承list,添加新功能或者修改功能

class List(list):   #继承了父类列表的属性
    def showmidle(self):
        mid=int(len(self)/2)
        return mid
l1=List('hello')   #因为List没写init,所以hello直接给了List里面的list
print(l1,type(l1))

2.授权

授权:授权是包装的一个特性,这种做法可以新建或者修改产品的原有功能,其他的
保持原样。授权是更新的功能是由新类的某部分来处理,但已存在功能授权给对象
的默认属性
解释程序:

class Open:
def __init__(self,filename,mode='r',encoding1='utf-8'):
self.file=open(filename,mode,encoding=encoding1) #将生成文件打开给self.file
def __getattr__(self, item):
return getattr(self.file,item) #虽然Open里面没有read,但是self.file里面有,所以找到read了
f1=Open('a.txt','w')
print(f1.read) #查看f1里面是否有read函数,虽然Open没有,触发了__getattr__

给实例化的类f1拥有文件操作的所有功能

class Open:
def __init__(self,filename,mode='r',encoding1='utf-8'):
self.file=open(filename,mode,encoding=encoding1) #将生成文件打开给self.file
def __getattr__(self, item):
return getattr(self.file,item) #虽然Open里面没有read,但是self.file里面有,所以找到write了
f1=Open('a.txt','w')
f1.write('asd')#查看f1里面是否有write函数,虽然Open没有,触发了__getattr_

在上一个程序中的改变型,如果类里面有写write,优先类里面的,不触发getattr

class Open:
def __init__(self,filename,mode='r',encoding1='utf-8'):
self.file=open(filename,mode,encoding=encoding1) #将生成文件打开给self.file
def __getattr__(self, item):
return getattr(self.file,item)
def write(self,wr):
print(wr)
f1=Open('a.txt','w')
f1.write('asd')

因此我们可以修改类中的write函数,使它在原有的write函数的基础上修改

class Open:
def __init__(self,filename,mode='r',encoding1='utf-8'):
self.file=open(filename,mode,encoding=encoding1) #将生成文件打开给self.file
def __getattr__(self, item):
return getattr(self.file,item) #虽然Open里面没有read,但是self.file里面有,所以找到read了
def write(self,wr):
x=getattr(self.file,'write')
xieru='已经修改 '+wr
x(xieru)
f1=Open('a.txt','w')
f1.write('asd')#查看f1里面是否有read函数,虽然Open没有,触发了__getattr__

面向对象进阶:

1.isinstance(obj,cls)检查obj是否是类cls实例化而来的

2.issubclass(sub,supper)检查sub类是否是supper的子类

3.getattribute,是getattr的大哥,不管里面有没有都会执行它

class Open:
x=10086
def __init__(self,filename,mode='r',encoding1='utf-8'):
self.file=open(filename,mode,encoding=encoding1) #将生成文件打开给self.file
def __getattr__(self, item):
print('没有哦')
def __getattribute__(self, item):
print('有')
f1 = Open('a.txt', 'w')
f1.x1 #没有也执行
f1.x #有也执行

4.item方法

用字典添加属性的时候会触发setitem,删除时触发delitem,查阅触发getitem

class Foo:
def __getitem__(self,item):
print('getitem')
def __setitem__(self,key,value):
print('setitem')
def __delitem__(self,key):
print('delitem')
f1=Foo()
print(f1.__dict__)
f1['name']='egon' #可见用字典的方式写入的时候会触发setitem
print(f1.__dict__)

由于使用的时候会触发,所以可以定义同样名字的来覆盖或者修改这些函数

class Foo:
def __getitem__(self,item):
print('chufa getitem',item)
def __setitem__(self,key,value):
print('chufa setitem')
self.__dict__[key]=value
def __delitem__(self,key):
print('chufa delitem')
self.__dict__.pop(key)
f1=Foo()
print(f1.__dict__)
f1['name']='egon' #可见用中括号字典的方式写入的时候会触发修改的setitem
print(f1.__dict__)
f1.name1='sb' #可见用点的方式写入的时候用的是内置的,不会触发修改的setitem
print(f1.__dict__)
del f1.name
print(f1.__dict__)
del f1['name1']
print(f1.__dict__)

5.改变对象的字符串显示

第一:正常的时候print实例化的结果

class Foo:
pass
f1=Foo()
print(f1) #<__main__.Foo object at 0x00B9E5E0>可以看见打印出来的是对象

第二:__str__改变print实例化出来的时候是自己想展示的字符串内容

class Foo:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return '改成字符串了,活人名字%s,岁数%s' %(self.name,self.age)
f1=Foo('sb1',100)
print(f1)

第三:__repr__改变print实例化出来的时候是自己想展示的字符串内容

如果还有__str__优先__repr__

class Foo:
def __init__(self,name,age):
self.name=name
self.age=age
def __repr__(self):
return '改成字符串了,活人名字%s,岁数%s' %(self.name,self.age)
f1=Foo('sb1',100)
print(f1)

6.自定义格式化format方法

第一,普通的format用法

x='{0}{0}'.format('dag')
print(x)

第二:在类里面自己自定义自己的__format__

format_dic={
'1':'{0.name}-{0.age}',
'2':'{0.name}的{0.age}'
}
class Foo:
def __init__(self,name,age):
self.name=name
self.age=age
def __format__(self,format_spec):
fm=format_dic[format_spec]
return fm.format(self)
f1=Foo('sb1',100)
print(format(f1,'2'))

7.__slots__节省实例内存

类下面的每个实例都会自己开辟自己的内存空间
每个实例都会有自己的__Dict__,因此很占空间,可以用__slots__把所有实例的dict整合到一个里

class Foo:
__slots__=['name','age']
f1=Foo()
print(Foo.__slots__)
print(f1.__slots__)
f1.name='sb1'
f1.age='11'
print(f1.name)
print(f1.age)
print(f1.__dict__) #可以看见有slots,__dict__就会消失

slots只能定义它里面固定的几个属性,不能添加其他的属性

class Foo:
__slots__=['name','age']
def __init__(self, name, age):
self.name = name
self.age = age
f1=Foo('sb1',100)
print(f1.name)
print(f1.age)
f1.abc='ssad' #可见在想添加新的属性abc时报错

8.文档注释__doc__,实例化调用doc,继承的子类调用不到

class Foo:
'are you silly b'
__slots__=['name','age']
def __init__(self, name, age):
self.name = name
self.age = age
f1=Foo('sb1',100)
print(Foo.__doc__)
print(f1.__doc__)

9.析构方法__del__,

清空内存时就会触发,无论是执行完毕还是出现删除实例操作都会触发

class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def __del__(self):
print('clear flash')
f1=Foo('sb1',100)

10.call方法,用于实例化也可以加括号运行

class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def __call__(self,*args,**kwargs):
print('call')
f1=Foo('sda',12)
f1() #实例加上空括号本质调用的是他的类里面的__call__

11.迭代器协议用于类

迭代数字

class Foo:
def __init__(self, n,):
self.n = n
def __iter__(self):
return self
def __next__(self):
self.n=self.n+1
return self.n
f1=Foo(12)
print(f1)
print(f1.__next__())
print(f1.__next__())
print(f1.__next__())

迭代字符串

class Foo:
i=0
def __init__(self, n,):
self.n = n
def __iter__(self):
return self
def __next__(self):
s=self.n[Foo.i]
Foo.i=Foo.i+1
return s
f1=Foo('asdadsad')
print(f1)
print(f1.__next__())
print(f1.__next__())
print(f1.__next__())

12.迭代器用于斐波那契数列

斐波那契额数列指的是前面两个数加起来等于第三个数
如112358

class fib:
def __init__(self):
self.a=1
self.b=1
def __iter__(self):
return self
def __next__(self):
(self.a,self.b)=(self.b,self.a+self.b)
return self.a
f1=fib()
print(f1.__next__())
print(f1.__next__())
print(f1.__next__())
print(f1.__next__())
print(f1.__next__())

13.软件开发规范

bin文件夹,里面放置启动文件    from src.xxx import xxxx.py
conf文件夹存放的是配置文件
db文件夹存放的是数据文件
lib文件夹存放的是库文件,公共的类库
log文件夹存放的是日志
src存放主逻辑函数
导入其他的文件里的文件时要加下环境变量
import sys,os
#os.path.dirname(__file__)获取它的上一级的绝对地址,嵌套之后是获取它
#上一级的上一级的绝对地址

#以下可以使用os获取上一层的上一层的地址
base_dir=os.path.dirname(os.path.dirname(__file__))
sys.path.append(base_dir)  #sys.path.append用于将其加入环境变量

Py-多态,封装,反射,描述符,包装标准类型,面向对象进阶的更多相关文章

  1. 一文帮你搞懂 Android 文件描述符

    介绍文件描述符的概念以及工作原理,并通过源码了解 Android 中常见的 FD 泄漏. 一.什么是文件描述符? 文件描述符是在 Linux 文件系统的被使用,由于Android基 于Linux 系统 ...

  2. linux一切皆文件之tcp socket描述符(三)

    一.知识准备 1.在linux中,一切皆为文件,所有不同种类的类型都被抽象成文件(比如:块设备,socket套接字,pipe队列) 2.操作这些不同的类型就像操作文件一样,比如增删改查等 二.环境准备 ...

  3. linux一切皆文件之Unix domain socket描述符(二)

    一.知识准备 1.在linux中,一切皆为文件,所有不同种类的类型都被抽象成文件(比如:块设备,socket套接字,pipe队列) 2.操作这些不同的类型就像操作文件一样,比如增删改查等 3.主要用于 ...

  4. 深入理解javascript对象系列第三篇——神秘的属性描述符

    × 目录 [1]类型 [2]方法 [3]详述[4]状态 前面的话 对于操作系统中的文件,我们可以驾轻就熟将其设置为只读.隐藏.系统文件或普通文件.于对象来说,属性描述符提供类似的功能,用来描述对象的值 ...

  5. usb驱动开发8之配置描述符

    前面分析了usb的四大描述符之端点描述符,接口描述符(每一个接口对应一个功能,与之配备相应驱动),下面是看配置描述符还是看设备描述符呢??我们知道,设备大于配置,配置大于接口,接口可以有多种设置. 我 ...

  6. usb驱动开发7之接口描述符

    前面struct usb_interface里表示接口设置的struct usb_host_interface被有意的飘过了,咱们在这节主要讲讲这个结构体,同样在include/linux/usb.h ...

  7. USB HID描述符【转】

    本文转载自: USB是个通用的总线,端口都是统一的.但是USB设备却各种各样,例如USB鼠标,USB键盘,U盘等等,那么USB主机是如何识别出不同的设备的呢?这就要依赖于描述符了.USB的描述符主要有 ...

  8. USB描述符概述

    在USB总线接口协议中,规定了一些标准的USB描述符,如表所示. 对于USB设备来说,有些USB描述符是必需的,例如: 设备描述符 配置描述符 字符串描述符 接口描述符 端点描述符 其余一些描述符并非 ...

  9. USB 描述符

    标准的USB设备有5种USB描述符:设备描述符,配置描述符,字符串描述符,接口描述符,端点描述符. // Standard Device Descriptor typedef struct { u8 ...

  10. usb协议分析-设备描述符配置包-描述符

    /* usb协议分析仅供大家参考---设备描述符配置包,设备描述符, 地址设置, 配置描述符, 字符串描述符 */ /* -1- usb设备描述符配置包 */ typedef struct _USB_ ...

随机推荐

  1. javase--&gt&semi;基础知识(二)

    1.算术运算符 7种:+,-,*,/,%,++,--;          --------------------注意不要想当然,按照类型规则来计算 ++在变量前,先加1再取变量使用 --同理 在变量 ...

  2. raw socket

    一个很newbee的例子,可惜还得改 import sys import time import socket import struct import random def SendPacketDa ...

  3. hdu 1057 &lpar;simulation&comma; use sentinel to avoid boudary testing&comma; use swap trick to avoid extra copy&period;) 分类: hdoj 2015-06-19 11&colon;58 25人阅读 评论&lpar;0&rpar; 收藏

    use sentinel to avoid boudary testing, use swap trick to avoid extra copy. original version #include ...

  4. Excel&lowbar;常用快捷键

    Ctrl+B        粗体Ctrl+U         下划线Ctrl+I         斜体Ctrl+5      删除线Ctrl+9      隐藏选中的行Ctrl+0      隐藏选中 ...

  5. SQL对字符串数组的处理详解

    原文地址:SQL字符串数组操作文章出处:DIY部落(http://www.diybl.com/course/7_databases/sql/sqlServer/2007106/76999.html) ...

  6. Ext&period;Net 使用总结之查询条件中的起始日期

    2.关于查询条件中起始日期的布局方式 首先上一张图,来展示一下我的查询条件的布局,如下: 大多数时候,我们的查询条件都是一个条件占一个格子,但也有不同的时候,如:查询条件是起始日期,则需要将这两个条件 ...

  7. 移动OA日程支持费用及评论

    业务介绍 AIO7系统最新更新版本在移动OA的日程管理进行改进,增加了创建费用的功能,且在日程批注上也可查看:在日程个人界面和批注界面都支持了评论功能.移动OA上日程对费用及评论的支持,方便用户外出时 ...

  8. M4——GPIO配置

    1.GPIO 简述: 通用输入输出(General Purpose Input Output)的简称,就是芯片引脚可以通过他们输出高电平或者低电平,也可以通过他们读取引脚的电平状态. 以STM32F4 ...

  9. 如何使用Linux的Crontab定时执行PHP脚本的方法&lbrack;转载&rsqb;

    首先说说cron,它是一个linux下的定时执行工具.根用户以外的用户可以使用 crontab 工具来配置 cron 任务.所有用户定义的 crontab 都被保存在/var/spool/cron 目 ...

  10. c&num; 匿名函数

    int t(){    Func<int> m=()=>3;    return m()+m();}