python之面向对象高级
一.__slots__
1.__slots__的概念:是一个变量,变量值可以是列表,元组,或者可迭代对象,也可以是一个字符串。
2.使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例是独立的)
3.为什么要用:节省内存,不会产生新的名称空间。
定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是每个实例定义一个字典;在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给实例添加新的属性了,只能用__slots__中定义的那些属性名。
4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再支持一些普通类特性,比如多继承。
5.应用场景:一个类产生N多个对象,产生对象的属性都是相同的,用__slots__来统一管理属性
class People:
__slots__=["x","y","z"]
p=People()
print(People.__dict__)
>>
{'__module__': '__main__', '__slots__': ['x', 'y', 'z'], 'x': <member 'x' of 'People' objects>, 'y': <member 'y' of 'People' objects>, 'z': <member 'z' of 'People' objects>, '__doc__': None} p.x=1
p.y=5
p.z=4
print(p.x,p.y,p.z)
>>
1 5 4 p.d=9 #报错
File "C:/python_fullstack_s4/day32/__slots__方法.py", line 14, in <module>
p.d=9
AttributeError: 'People' object has no attribute 'd' class Foo:
__slots__=['name','age'] f1=Foo()
f1.name='alex'
f1.age=18
print(f1.__slots__) f2=Foo()
f2.name='egon'
f2.age=19
print(f2.__slots__)
>>
['name', 'age']
['name', 'age']
#f1与f2都没有属性字典了,统一归__slots__管,节省内存
print(f1.__dict__)#报错
>>
Traceback (most recent call last):
File "C:/python_fullstack_s4/day32/__slots__方法.py", line 23, in <module>
print(f1.__dict__)
AttributeError: 'Foo' object has no attribute '__dict__'
二.__iter__ __next__
可迭代对象是有方法__iter__()
迭代器是有方法__next__()
因而可以自己构建一个类, 使得它的对象, 既是一个可迭代对象, 也是一个迭代器
from collections import Iterable,Iterator#导入模块 检查是否hi可迭代对象或迭代器
class Foo:
def __init__(self,start):
self.start=start
def __iter__(self):
return self
def __next__(self):
if self.start>10:#设置数据限制,当self.start>10时,停止运行
raise StopIteration
n=self.start
self.start+=1
return n
f=Foo(0)
# print(isinstance(f,Iterable))
for i in f:
print(i) >>
0
1
2
3
4
5
6
7
8
9
10
三.__doc__
__doc__是类的描述信息
该属性无法继承给子类
四.
__module__表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
class Bar():
pass
b=Bar()
print(b.__class__)
print(b.__module__)
>>
<class '__main__.Bar'>
__main__
五.__del__
析构方法,当对象在内存中被释放时,自动触发执行
class Open:
def __init__(self,filepath,mode="r",encode="utf8"):
self.f=open(filepath,mode=mode,encoding=encode)
def write(self):
pass
def __del__(self):#产生的对象被垃圾处理时
# 会触发__del__
print("--->del")
self.f.close() f=Open("a.txt","w")
del f#如果手动删除,直接触发,再执行别的程序
六.__enter__ __exit__
上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法
用途:
- 使用with语句的目的是把代码块放在with中执行,with结束后,自动完成清理工作,无须手动干预
- 在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制
class Open:
def __init__(self,name):
self.name=name def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
# return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊') with Open('a.txt') as f:
print('=====>执行代码块') >>
出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
=====>执行代码块
with中代码块执行完毕时执行我啊
抛出异常
with语句中代码块出现异常,则with后的代码都无法执行
class Foo:
def __enter__(self):
print("enter")
return 11111
def __exit__(self, exc_type, exc_val, exc_tb):
print("exit")
print("exc_type",exc_type)#异常类型
print("exc_val",exc_val)#异常值
print("exc_tb",exc_tb)#追溯信息 with Foo():#1.with加对象()就回触发enter的运行
print("1111")#2.打印
raise NameError()#只要抛出异常,子代码块就运行完毕
#触发exit的运行
print("******************")#不会运行
print("999999999999999999999999")#子代码运行结束后(无异常)
#正常运行 >>
Enter
1111
exit
exc_type <class 'NameError'>
exc_val
exc_tb <traceback object at 0x02EE1DA0>
Traceback (most recent call last):
File "C:/python_fullstack_s4/day32/上下文管理协议.py", line 17, in <module>
raise NameError()#只要抛出异常,子代码块就运行完毕
NameError异常解决
如果__exit()返回值为True,那么异常就会被清空,就好像什么都没发生,with后的语句正常执行
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
print(exc_type)
print(exc_val)
print(exc_tb)
return True
with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError('***着火啦,救火啊***')#传给exc_val
print('0'*100) #------------------------------->会执行
>>
出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
=====>执行代码块
with中代码块执行完毕时执行我啊
<class 'AttributeError'>
***着火啦,救火啊***
<traceback object at 0x02C51E68>
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
七.__call__
对象后面加括号,触发执行
构造方法的执行是由创建对象触发的,即对象=类名();
对于__call__方法的执行是由对象后加括号触发的,即对象()或者类()()
class People:
def __init__(self,name):
self.name=name
def __call__(self, *args, **kwargs):
print("call")
p=People("karina")
p()#实例也变成一个可调用对象
>>
call
八.元类
元类是类的类,是类的模板
元类是用来控制如何创建类的,正如类是创建对象的模板一样
元类的实例为类,正如类的实例是对象(Foo是type的类,f1对象是Foo的一个实例)
Type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象
产生类的方法
1.
class Foo:
def func(self):
print("from func")
f1=Foo()
f1.func()
>>
from func
2.
格式
类名=type(class_name,class_bases(父类),class_dict({}))
def func(self):
print("from func")
x=1
Foo=type("Foo",(object,),dict({}))
print(Foo)
print(type(Foo))
print(Foo.__dict__)
>>
<class '__main__.Foo'>
<class 'type'>
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
新建对象的过程
首先, 类要生成对象, 类本身需要可调用
针对于基类, 类是基类的对象, 也就是说在基类中, 需要有一个__call__()函数, 而这个函数, 是在类的__init__之前执行的
在基类的__call__()方法中, 需要使用self.__new__(self)来创建一个空对象, 这个对象就是类
有了类之后就可以调用原有的方法__init__(), 这时在其中就是熟悉的生成对象了
最后再返回这个类就行了
class MyMetaclass(type):
def __call__(self, *args, **kwargs):
obj = self.__new__(self)
self.__init__(obj, *args, **kwargs) # obj.name='egon'
return obj class People(metaclass=MyMetaclass):
def __init__(self, name):
self.name = name whc = People('whc')
print(whc.name)
python之面向对象高级的更多相关文章
- Python自动化 【第七篇】:Python基础-面向对象高级语法、异常处理、Scoket开发基础
本节内容: 1. 面向对象高级语法部分 1.1 静态方法.类方法.属性方法 1.2 类的特殊方法 1.3 反射 2. 异常处理 3. Socket开发基础 1. ...
- Python之路,Day8 - Python基础 面向对象高级进阶与socket基础
类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...
- 【Python】[面向对象高级编程] 多成继承,定制类,使用枚举
1.多成继承 class SmallDog(Animal,Dog) pass MixIn就是一种常见的设计. 2.定制类类似__slots__这种形如 __xxx__ 的变量或者函数名,在python ...
- python学习 面向对象高级编程
---恢复内容开始--- 面向对象编程---oop,是一种编程思想,oop把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数 ...
- 【Python】[面向对象高级编程] 使用__slots__,使用@property
1.使用 __slots__ 给实例绑定方法, >>> def set_age(self, age): # 定义一个函数作为实例方法 ... self.age = age .. ...
- python高级之面向对象高级
python高级之面向对象高级 本节内容 成员修饰符 特殊成员 类与对象 异常处理 反射/自省 单例模式 1.成员修饰符 python的类中只有私有成员和公有成员两种,不像c++中的类有公有成员(pu ...
- 第五篇:python高级之面向对象高级
python高级之面向对象高级 python高级之面向对象高级 本节内容 成员修饰符 特殊成员 类与对象 异常处理 反射/自省 单例模式 1.成员修饰符 python的类中只有私有成员和公有成员两 ...
- 简学Python第七章__class面向对象高级用法与反射
Python第七章__class面向对象高级用法与反射 欢迎加入Linux_Python学习群 群号:478616847 目录: Python中关于oop的常用术语 类的特殊方法 元类 反射 一.P ...
- python笔记 面向对象编程从入门到高级
目录: 一.概念 二.方法 2.1组合 2.2继承 2.3多态 2.4封装 2.5归一化设计 三.面向对象高级 3.1 反射(自省) 3.2 内置方法__getatter__, __ ...
随机推荐
- mysql恢复ibd文件
1.将原表删除,包括ibd和frm文件 2.重新创建表结构. 3.丢弃表空间 alter table tableName discard tablespace; 4.将要恢复的ibd文件拷贝到数据库目 ...
- Multidex(二)之Dex预加载优化
Multidex(二)之Dex预加载优化 https://www.jianshu.com/p/2891599511ff
- 【转载】DDD分层架构的三种模式
引言 在讨论DDD分层架构的模式之前,我们先一起回顾一下DDD和分层架构的相关知识. DDD DDD(Domain Driven Design,领域驱动设计)作为一种软件开发方法,它可以帮助我们设计高 ...
- python全栈开发day58-mysql存储过程,权限,索引,慢日志,执行计划,分页优化处理
1.存储过程 delimiter // create procedure insert_data(in rows int) begin DECLARE n INT DEFAULT 1; drop ta ...
- Flask Web中用MySQL代替SQLite
由于.sqlite文件操作的诸多不便,决定常识用MySQL代替书上的SQLite作为数据库. 1.在虚拟环境中安装mysql-Python具体步骤为: <1> 安装python-dev s ...
- 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意你不能在买入股票前卖出股票. 示例 ...
- day 42 mycql 数据类型
关于性别字段的存储数据类型选用 -- 性别字段 create table actor2 (id int not null auto_increment primary key,name char(32 ...
- 3dsmax不同版本 pyside qt UI 设置max窗口为父窗口的方法
3dsmax不同版本 pyside qt widget 设置 max 窗口为父窗口的方法 前言: 3dsmax 在 2014 extension 之后开始集成 Python 和 PySide,但是在版 ...
- vdom,diff,key 算法的了解
<ul id='list'> <li class='item'>Item1</li> <li class='item'>Item2 </li> ...
- HDU 1710 (二叉树的前序和中序,求后序)
题目链接 题目大意: 输入二叉树的前序.中序遍历,请输出它的后序遍历 #include <stdio.h> #include <string.h> ; // 长度为n s1 前 ...