一、如何派生内置不可变类型并修改实例化行为
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)
print IntTuple([1, 2, 6, 'abc', -1, {'a': 5}, 7])
二、如何为创建大量实例节省内存
class player1(object):
def __init__(self, uid, name):
self.uid = uid
self.name = name
class player2(object):
__slots__ = ['uid', 'name']
def __init__(self, uid, name):
self.uid = uid
self.name = name
p1 = player1('001', 'jim')
p2 = player2('001', 'jim')
p1.x = 100
p1.y = 0
p1.__delattr__('x')
print set(dir(p1)) - set(dir(p2))
import sys
print sys.getsizeof(p1.__dict__)
三、如何让对象支持上下文管理
from telnetlib import telnetlib
from sys import stdin, stdout
from collecttions import deque
class TelnetClient(object):
def __init__(self, addr, port=23)
self.addr = addr
self.port = port
self.tn = None
def start(self):
# user
t = self.tn.read_until('login:')
stdout.write(t)
user = stdin.readline()
self.tn.write(user)
# password
t = self.tn.read_until('Password:')
if t.startswith(user[:-1]): t = t[len(user) + 1:]
stdout.write(t)
self.tn.write(stdin.readline())
t = self.tn.read.until('$ ')
stdout.write(t)
while True:
uinput = stdin.readline()
if not uinput:
break
self.history.append(uinput)
self.tn.write(uinput)
t = self.tn.read_until('$ ')
stdout.write(t[len(uinput) + 1:])
def __enter__(self):
self.tn = Telnet(self.addr, self.port)
self.history = deque()
return self
pass
def __exit__(self, exc_type, exc_val, exc_tb):
self.cn.close()
self.cn = None
with open(self.addr + '_history.txt', 'w') as f:
f.writelines(self.history)
with TelnetClient('127.0.0.1') as client:
client.start()
四、如何创建可管理的对象属性
class Circle(object):
def __init__(self,radius):
self.radius = radius
def getRadius(self):
return round(self.radius,2)
def setRadius(self,value):
if isinstance(value,(int,long,float)):
self.radius=float(value)
else:
raise ValueError('wrong type')
R = property(fget=getRadius,fset=setRadius,)
c=Circle(3.5)
print c.radius
c.radius='abc'
print c.radius
c.R=53.3473934
print c.R
五、如何让类支持比较操作
from functools import total_ordering
from abc import ABCMeta, abstractmethod
@total_ordering # 添加这个装饰器后,只需要重载__ltf__,__eq__ 两个比较函数,其它的比较函数装饰器会根据这两个判断生成。
class Shape(object):
@abstractmethod
def area(self):
pass
def __lt__(self, other):
print 'in __lt__'
if not isinstance(other, Shape):
raise TypeError('other is not Shape')
return self.area() < other.area()
def __eq__(self, other):
print 'in __eq__'
if not isinstance(other, Shape):
raise TypeError('other is not Shape')
return self.area() == other.area()
class Rect(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 = Rect(6, 2)
r2 = Rect(2, 2)
c = Circle(1)
print c <= r2
六、如何使用描述符对实例属性做类型检查
class Attr(object):
def __init__(self, name, type_):
self.name = name
self.type_ = type_
def __get__(self, instance, cls):
print 'in __get__', self, instance, cls
return instance.__dict__[self.name]
def __set__(self, instance, value):
print 'in __set__', self, instance, value
if not isinstance(value, self.type_):
raise TypeError('is not format ')
instance.__dict__[self.name] = value
def __del__(self, instance):
print 'in __del__'
del instance.__dict__[self.name]
class Person(object):
name = Attr('name', str)
age = Attr('name', int)
height = Attr('height', float)
p = Person()
p.name = 'litaifa'
print p.name
p.name = 12
七、如何在环状数据结构中管理内存
import sys,weakref
class Data(object):
def __init__(self,value,owner):
self.value=value
self.owner=weakref.ref(owner)
def __str__(self):
return "%s's data,value is %s" % (self.owner(),self.value)
def __del__(self):
print 'in Data.__del__ %s ' % (self.value)
class Node(object):
def __init__(self,value):
self.data=Data(value,self)
def __del__(self):
print 'in Node.__del__ '
node=Node(100)
print node.data
print sys.getrefcount(node)-1
del node
raw_input("wait...")
八、如何通过实例方法名字的字符串调用方法
from operator import methodcaller
class Rect(object):
def __init__(self, w, h):
self.w = w
self.h = h
def area(self):
return self.w * self.h
class Circle(object):
def __init__(self, r):
self.r = r
def get_area(self):
return self.r ** 2 * 3.14
def getArea(shape):
for name in ['area', 'get_area']:
f = getattr(shape, name, None)
if f:
return f()
return methodcaller(name)(shape)
shapes = [Rect(2, 3), Circle(1)]
print map(getArea, shapes)