Python168的学习笔记6
如何派生内置不可变类型并修改实例化行为。
个人理解,如何派生出自己想要的类。
class IntTuple(tuple): def __new__(cls,iterable):
g = (x for x in iterable if isinstance(x, int) and x>0)
return super(IntTuple,cls).__new__(cls,g) def __init__(self,iterable):
super(IntTuple,self).__init__(iterable) t = IntTuple([1,-1,'abc',6,[7,'y'],3])
print t
类的创建是在__new__中实现的,所以要修改new。
关于使用__slots__,在创建class时,定义slots属性,声明实例属性列表,这就等于关闭掉__dict__属性,dict的作用是允许对class进行动态添加属性。使用slots可以节省内存,对封装有好处。
关于上下文管理,也就是在class中设置__enter__,__exit__属性,这样就可以配合with使用了。ps:with语句中,无论如何都会执行exit方法。
在设置__enter__属性时,要注意返回的对象是不是self,一般来说都是。
在设置__exit__属性时,要注意接收的参数, def __exit__(self,exc_type,exc_val,exc_tab),需要接收异常信息。
注意,如果在exit中设置了return Ture。则错误会被包在with中而不传回给最上层。
关于property的用法。
class Circle(object):
def __init__(self,r):
self.r = r def getR(self):
return round(self.r,2)#四舍五入两位小数 def setR(self,value):
if not isinstance(value,(int,long,float)):
raise ValueError('wrong type.')
self.r = float(value) def getArea(self):
return round(self.r ** 2* pi) R = property(getR,setR)#将方法定义到属性 c =Circle(3.2)
print c.R
c.R = 5
为类添加比较的属性,如__lt__,__le__,__gt__,__ge__,__eq__,__ne__这些属性。(小于,小于等于,大于,大于等于,等于,不等于)
比较两个类的大小,如 r1<r2 实际上就是 r1.__lt__(r2)方法的调用。
但是如果要添加6个属性显得很麻烦,所以可以使用functools.total_ordering方法,将其作为装饰器,赋给class,然后只用定义__lt__,__eq__就可以实现6个属性的比较了。
from functools import total_ordering
from abc import abstractmethod,ABCMeta @total_ordering
class Shape(object):
__metaclass__ = ABCMeta#定义这个类为抽象类,不可以被实例化
@abstractmethod#声明定义抽象方法,让各个子类去完善
def area(self):
pass def __lt__(self,obj):
if not isinstance(obj,Shape):
raise TypeError('obj is not shape.')
return self.area() <obj.area() def __eq__(self,obj):
if not isinstance(obj,Shape):
raise TypeError('obj is not shape.')
return self.area() == obj.area() class Rectangle(Shape):
def __init__(self,w,h):
self.w = w
self.h = h def area(self):
return self.w *self.h class Circle(Shape):
def __init__(self,r):
self.r = r def area(self):
return self.r ** 2 *3.14 r1 = Rectangle(3,5)
r2 = Rectangle(5,5)
c1 = Circle(5)
print r1 > r2
print c1 > r1
ps:要注意ABCMeta,abstractmethod的作用,理解抽象类以及抽象方法的定义。
深入了解类的构成,如 __get__,__set__,__del__ 这些方法的作用。
#coding:utf8
class Attr(object):
def __init__(self,name,type_):
self.name = name
self.type_ = type_ def __get__(self,instance,cls):
return instance.__dict__[self.name] def __set__(self,instance,value):
if not isinstance(value,self.type_):
raise TypeError('expected an %s' % self.type_)
instance.__dict__[self.name] = value def __delete__(self,instance):
del instance.__dict__[self.name] class Person(object):
name = Attr('name',str)
age = Attr('age',int)
height = Attr('height',float) p = Person() p.age = ''
print p.age#这里就会报错
引入弱引用weakref的概念,弱引用可以创建一种能访问对象,但是不增加访问计数的对象。
ps:当对象被引用时,对象的引用计数+1,而当对象的引用计数为0时,对象将被回收。弱引用的好处是,在某种循环引用里,解决回收不及时的问题。
#coding:utf8
import weakref class Data(object):
def __init__(self,value,owner):
self.owner = weakref.ref(owner)#如果不是弱引用,则删除实例也不会回收
self.value = value def __del__(self):#回收函数
print 'in Data.__del__' class Node(object):
def __init__(self,value):
self.data = Data(value,self) def __del__(self):
print 'in Node.__del__' node = Node(100)
del node
ps:注意,需要引用 弱引用的对象时,要用其方法,如:self.owner = weakref.ref(owner),调用self.owner时应为self.owner()
通过实例化 方法的名字 来调用
class s1(object):
def A(self):
return 'A' class s2(object):
def B(self):
return 'B' class s3(object):
def C(self):
return 'C' def getS(s):
for name in ('A','B','C'):
f = getattr(s, name,None)#在这里寻找对应的方法,如果找不到就返回none
if f:
return f() a = s1()
b = s2()
c = s3()
t = [a,b,c]
print map(getS,t)
用operator.methodcaller也有类似功能。但是不太明白为什么要用这个。
最新文章
- 第七章 人工智能,7.6 DNN在搜索场景中的应用(作者:仁重)
- VisualSVN Server的配置和使用方法(转)
- 学习NSRulerView
- Highcharts使用简例 + 异步动态读取数据
- copy 和 strong(或retain)的区别
- 系统级I/O
- POJ3009 Curling
- android 自动化压力测试-monkey 3 命令参数
- dynamic_cast
- c++中string类的详解
- 常用linux命令和配置
- jQuery prop 全选和全不全
- Web 版 PowerDesigner (Canvas) 技术
- python2.6升级2.7
- ZFS建池建卷和格式化
- nexus 随笔
- 1.关于Java
- mysql 查询优化~sql优化通用
- SpringCloud报错: ";Field discoveryClient in com.controller.DcController required a bean of type &#39;com.netflix.discovery.DiscoveryClient&#39; that could not be found.";
- 【读书笔记】iOS-关闭键盘的2种方法