classDateStructure:def__init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethoddeftoday(cls):# 重新初始化,替代__init__print(cls)
t = time.localtime()return cls(t.tm_year, t.tm_mon, t.tm_mday)# a = DateStructure(2012, 12, 21) # Primary# b = DateStructure.today()# print(b.year, b.month, b.day)classNewDate(DateStructure):pass# c = DateStructure.today() # Creates an instance of Date (cls=Date)# d = NewDate.today() # Creates an instance of NewDate (cls=NewDate)
创建不调用init方法的实例
classDateStructure2:def__init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethoddeftoday(cls):
d = cls.__new__(cls)# 使用__new__绕过__init__
t = time.localtime()
d.year = t.tm_year
d.month = t.tm_mon
d.day = t.tm_mday
return d
# x = DateStructure2.today()# print(x.year)
利用Mixins扩展类功能
# 你有很多有用的方法,想使用它们来扩展其他类的功能。但是这些类并没有任何继# 承的关系。因此你不能简单的将这些方法放入一个基类,然后被其他类继承classLoggedMappingMixin:
__slots__ =()# 混入类都没有实例变量,因为直接实例化混入类没有任何意义def__getitem__(self, key):print('Getting '+str(key))returnsuper().__getitem__(key)def__setitem__(self, key, value):print('Setting {} = {!r}'.format(key, value))returnsuper().__setitem__(key, value)def__delitem__(self, key):print('Deleting '+str(key))returnsuper().__delitem__(key)classSetOnceMappingMixin:
__slots__ =()def__setitem__(self, key, value):if key in self:raise KeyError(str(key)+' already set')returnsuper().__setitem__(key, value)classStringKeysMappingMixin:
__slots__ =()def__setitem__(self, key, value):ifnotisinstance(key,str):raise TypeError('keys must be strings')returnsuper().__setitem__(key, value)classLoggedDict(LoggedMappingMixin,dict):# 通过多继承混入类pass# d = LoggedDict()# d['x'] = 23# print(d['x'])# del d['x']
classNodeX:def__init__(self, value):
self.value = value
self._parent =None
self.children =[]def__repr__(self):return'Node({!r:})'.format(self.value)# property that manages the parent as a weak-reference@propertydefparent(self):returnNoneif self._parent isNoneelse self._parent()@parent.setterdefparent(self, node):# 弱引用就是一个对象指针,它不会增加它的引用计数弱引用就是一个对象指针# 它不会增加它的引用计数
self._parent = weakref.ref(node)defadd_child(self, child):
self.children.append(child)
child.parent = self
# root = NodeX('parent')# c1 = NodeX('child')# root.add_child(c1)# print(c1.parent)# del root# print(c1.parent)
让类支持比较操作
# 装饰器 functools.total_ordering# 你只需定义一个 __eq__() 方法,外加其他方法 (__lt__, __le__, __gt__, or# __ge__) 中的一个即可。然后装饰器会自动为你填充其它比较方法classRoom:def__init__(self, name, length, width):
self.name = name
self.length = length
self.width = width
self.square_feet = self.length * self.width
@total_orderingclassHouse:def__init__(self, name, style):
self.name = name
self.style = style
self.rooms =list()@propertydefliving_space_footage(self):returnsum(r.square_feet for r in self.rooms)defadd_room(self, room):
self.rooms.append(room)def__str__(self):return'{}: {} square foot {}'.format(self.name,
self.living_space_footage,
self.style)def__eq__(self, other):return self.living_space_footage == other.living_space_footage
def__lt__(self, other):return self.living_space_footage < other.living_space_footage
# h1 = House('h1', 'Cape')# h1.add_room(Room('Master Bedroom', 14, 21))# h1.add_room(Room('Living Room', 18, 20))# h1.add_room(Room('Kitchen', 12, 16))# h1.add_room(Room('Office', 12, 12))# h2 = House('h2', 'Ranch')# h2.add_room(Room('Master Bedroom', 14, 21))# h2.add_room(Room('Living Room', 18, 20))# h2.add_room(Room('Kitchen', 12, 16))# h3 = House('h3', 'Split')# h3.add_room(Room('Master Bedroom', 14, 21))# h3.add_room(Room('Living Room', 18, 20))# h3.add_room(Room('Office', 12, 16))# h3.add_room(Room('Kitchen', 15, 17))# houses = [h1, h2, h3]# print('Is h1 bigger than h2?', h1 > h2) # prints True# print('Is h2 smaller than h3?', h2 < h3) # prints True# print('Is h2 greater than or equal to h1?', h2 >= h1) # Prints False# print('Which one is biggest?', max(houses)) # Prints 'h3: 1101-square-foot-Split# print('Which is smallest?', min(houses)) # Prints 'h2: 846-square-foot Ranch
创建缓存实例
# 在创建一个类的对象时,如果之前使用同样参数创建过这个对象,你想返回它的缓存引用classSpamX:def__init__(self, name):
self.name = name
_spam_cache = weakref.WeakValueDictionary()defget_spam(name):if name notin _spam_cache:
s = SpamX(name)
_spam_cache[name]= s
else:
s = _spam_cache[name]return s
# a = get_spam('foo')# b = get_spam('bar')# c = get_spam('foo')# print(a is b)# print(a is c)