一、__setitem__,__getitem,__delitem__

#把对象操作属性模拟成字典的格式
class Foo:
def __init__(self,name):
self.name=name
def __getitem__(self, item):
print('getitem===>')
return self.__dict__[item]
def __setitem__(self, key, value):
print('setitem===>')
self.__dict__[key]=value
def __delitem__(self, key):
print('delitem===>')
self.__dict__.pop(key) f=Foo('luchuan')
f['name']='luchuangao'
print(f['name'])
f['age']=18
print(f.__dict__)
del f['age']
print(f.__dict__)

把对象操作属性模拟成字典的格式

二、__slots__

__slots__的好处是限制设置规定得属性,剩内存。

1、__slots__是什么:是一个类变量,变量值可以是列表、元组、或可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)
2、引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例是独立的)
3、为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__。在定义__slots__后,__slots__就会实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典,跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是不能给实例添加新的属性,只能使用__slots__中定义的那些属性名。
4、注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再支持一些普通类特性了,比如多继承。大多数情况下,应该只在那些经常被使用到的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象。
关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。更多的是用来作为内存优化工具。

说明文档

class People:
__slots__=['x','y','z'] p=People()
print(People.__dict__) p.x=1
p.y=2
p.z=3
# p.x=4 #报错
print(p.x,p.y,p.z)
# print(p.__dict__) p不再有属性字典__dict__,统一归__slots__管,节省内存

应用实例

三、__next__和__iter__实现迭代器协议

from collections import Iterable,Iterator
class Foo:
def __init__(self,start):
self.start=start def __iter__(self):
return self def __next__(self):
return 'SB' f=Foo(0)
# f.__iter__()
# f.__next__() print(isinstance(f,Iterable))
print(isinstance(f,Iterator)) print(next(f)) #f.__next__()
print(next(f)) #f.__next__()
print(next(f)) #f.__next__() for i in f: # res=f.__iter__() #next(res),无限循环
print(i)

简单姿势一

from collections import Iterable,Iterator
class Foo:
def __init__(self,start):
self.start=start def __iter__(self):
return self def __next__(self):
if self.start > 10:
raise StopIteration
n=self.start
self.start+=1
return n f=Foo(0) print(next(f))
print(next(f))
print(next(f))
for i in f:
print('====>',i)

简单姿势二

class Range:
''
def __init__(self,start,end):
self.start=start
self.end=end def __iter__(self):
return self def __next__(self):
if self.start == self.end:
raise StopIteration
n=self.start
self.start+=1
return n for i in Range(0,3):
print(i)

高级姿势三

四、__doc__

class Foo:
'我是描述信息'
pass class Bar(Foo):
pass
print(Foo.__doc__)
print(Bar.__doc__) #该属性无法继承给子类

小小暧昧

注:__doc__属性无法继承给子类

五、__module__和__class__

__module__表示当前操作的对象在那个模块
__class__表示当前操作的对象的类是什么

class Foo:
'我是描述信息'
pass class Bar(Foo):
pass
# print(Bar.__doc__) #该属性无法继承给子类 b=Bar()
print(b.__class__)
print(b.__module__)
print(Foo.__module__)
print(Foo.__class__) # 输出结果:
# <class '__main__.Bar'> #b由Bar类产生
# __main__ #表示当前模块
# __main__
# <class 'type'>

哼哈二将

六、__del__

    析构方法,当对象在内存中被释放时,自动触发执行
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

说明文档

import time
class Open:
def __init__(self,filepath,mode='r',encode='utf-8'):
self.f=open(filepath,mode=mode,encoding=encode) def write(self):
pass def __getattr__(self, item):
return getattr(self.f,item) def __del__(self):
print('----->del')
self.f.close() f=Open('a.txt','w')
f1=f #引用计数为2
del f
# time.sleep(1000000000)
print('=========>') #测试f1=f注释后得效果,只有f 引用计数为1

帅你一脸

七、__enter__和__exit__

一般在操作文件时这样写:

with open('a.txt') as f:
  '代码块'

上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__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('=====>执行代码块')
# print(f,f.name) 上下文管理协议

上下文管理协议

__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则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) with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError('***着火啦,救火啊***')
print(''*100) #------------------------------->不会执行

如果__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('***着火啦,救火啊***')
print(''*100) #------------------------------->会执行

用途或者说好处:
1、使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预。
2、在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以再__exit__中定制自动释放资源的机制,你无须再去关系这个文件,这将大有用处。

class Open:
def __init__(self,filepath,mode,encode='utf-8'):
self.f=open(filepath,mode=mode,encoding=encode)
self.filepath=filepath
self.mode=mode
self.encoding=encode def write(self,line):
print('write')
self.f.write(line) def __getattr__(self, item):
return getattr(self.f,item) def __enter__(self):
return self def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
return True with Open('a.txt','w') as write_file: #write_file=Open('a.txt','w')
write_file.write('123123123123123\n')
write_file.write('123123123123123\n')
print(sssssssssssssss)
write_file.write('123123123123123\n')

高潮部分

八、__call__

对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象=类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象()或者类()

class People:
def __init__(self,name):
self.name=name def __call__(self, *args, **kwargs):
print('call') p=People('egon')
print(callable(People))
print(callable(p)) p()

小计量

九、metaclass

1、引子

class Foo:
pass f1=Foo() #f1是通过Foo类实例化的对象

Python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载class的时候就会创建一个对象(这里的对象指的是类而非类的实例)

以上可以看出f1是由Foo类产生的对象,而Foo本身也是对象。

type函数可以查看类型,也可以用来查看对象的类,二者是一样的

print(type(f1)) # 输出:<class '__main__.Foo'>  表示,obj 对象由Foo类创建
print(type(Foo)) # 输出:<type 'type'>

2、什么是元类?

元类是类的类,可以控制类的行为,是类的模板,正如类是创建对象的模板。
元类的实例为类,正如类的实例为对象(f1对象是Foo类的一个实例,Foo类是type类的一个实例)
type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象。

3、创建类的两种方式

方式一:

class Foo:
def func(self):
print('from func')

方式二:

def func(self):
print('from func')
x=1
Foo=type('Foo',(object,),{'func':func,'x':1})

4、一个类没有声明自己的元类,默认它的元类就是type,除了使用元类type, 用户也可以通过继承type来自定义元类(顺便也可以了解下元类是如何控制类的创建,工作流程是什么)

其他内容待补充,生产环境很少修改,原理需要理解。

python基础之类的进阶的更多相关文章

  1. 十三. Python基础(13)--生成器进阶

    十三. Python基础(13)--生成器进阶 1 ● send()方法 generator.send(value) Resumes the execution, and "sends&qu ...

  2. python基础篇之进阶

    python基础篇之进阶 参考博客:http://www.cnblogs.com/wupeiqi/articles/5115190.html python种类 1. cpython  使用c解释器生产 ...

  3. Python基础—面向对象(进阶篇)

    通过上一篇博客我们已经对面向对象有所了解,下面我们先回顾一下上篇文章介绍的内容: 上篇博客地址:http://www.cnblogs.com/phennry/p/5606718.html 面向对象是一 ...

  4. Python之路,Day8 - Python基础 面向对象高级进阶与socket基础

    类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...

  5. 学习PYTHON之路, DAY 8 - PYTHON 基础 8 (面向对象进阶)

    类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的 ...

  6. 周末班:Python基础之面向对象进阶

    面向对象进阶 类型判断 issubclass 首先,我们先看issubclass() 这个内置函数可以帮我们判断x类是否是y类型的子类. class Base: pass class Foo(Base ...

  7. 周末班:Python基础之函数进阶

    迭代器和生成器 迭代和可迭代 什么是迭代(iteration)? 如果给定一个list或tuple,我们要想访问其中的某个元素,我们可以通过下标来,如果我们想要访问所有的元素,那我们可以用for循环来 ...

  8. python基础之 编码进阶,文件操作和深浅copy

    1.编码的进阶 字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码.即先将其他编码的字符串解码(decode)成unicode,再从unic ...

  9. python基础_面向对象进阶

    @property装饰器 之前我们讨论过Python中属性和方法访问权限的问题,虽然我们不建议将属性设置为私有的,但是如果直接将属性暴露给外界也是有问题的,比如我们没有办法检查赋给属性的值是否有效.我 ...

  10. Python之路【第六篇】python基础 之面向对象进阶

    一 isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象  和  issubclass(su ...

随机推荐

  1. 报错"the microsoft.jet.oledb.4.0 provider is not registered on the local machine"解决方案

    报错提示:"the microsoft.jet.oledb.4.0 provider is not registered on the local machine" 错误起因:wi ...

  2. 点滴积累【JS】---JQuery实现条形统计图,适用于选择题等统计

    效果: 思路:前台JS实现动态数据效果,后台可以拼接字符串或者用JSON加载数据 代码: <%@ Page Language="C#" AutoEventWireup=&qu ...

  3. C#.NET中使用BackgroundWorker在模态对话框中显示进度条

    这里是一个示例,其中展示了如何使用Backgroundworker对象在模态对话框中显示后台操作的实时进度条. 首先是主窗体代码: using System; using System.Collect ...

  4. hive执行更新和删除操作

    Hive从0.14版本开始支持事务和行级更新,但缺省是不支持的,需要一些附加的配置.要想支持行级insert.update.delete,需要配置Hive支持事务. 一.Hive具有ACID语义事务的 ...

  5. Ubuntu下修改tomcat6默认的8080端口

    $ sudo vi /etc/tomcat6/server.xml   将 <Connector port="8080" protocol="HTTP/1.1&qu ...

  6. C++读取Sql Server

    代码如下: // ReadSqlConsole.cpp: 主项目文件. #include "stdafx.h" #include <iostream> #include ...

  7. Squares - poj 2002(hash)

    枚举两个点作为一条边,求出正方形的另外两个点,利用hash查找另外两个点. #include<stdio.h> #include<string.h> #include<s ...

  8. C++ 抽象类二(抽象类的基本语法)

    //抽象类的基本语法 #include<iostream> using namespace std; /* 有关多继承的说明 被实际开发经验抛弃的多继承 工程开发中真正意义上的多继承是几乎 ...

  9. Mathematica之基本操作

    1.清楚所有变量 Clear["Global`*"];

  10. 第一百三十六节,JavaScript,封装库--事件绑定

    JavaScript,封装库--事件绑定 在函数库添加两个函数 添加事件绑定函数 删除事件绑定函数 添加事件绑定函数 /** addEvent()函数库函数,跨浏览器添加事件绑定,注意:传入事件名称时 ...