构造和初始化
-
__new__
用来调用这个类,并返回这个类的实例 -
__init__
只是将传入的参数来初始化该实例
控制属性访问
__getattr__(self, name):
当用户视图获取一个不存在的属性时的行为。这适用于对普通拼写错误和重定向,对获取一些不建议的属性时,给予警告或者处理一个AttributeError。只有当调用不存在的属性时,会被返回。__setattr__(self, name, value):
一个封装的解决方案,无论属性值是否存在,它都允许你定义对属性赋值行为。实现__setattr__
要避免无限的递归错误
# uncorrect
def __setattr__(self, name, value):
self.name = value
# 没当属性被赋值时,``__setattr__()``会被调用,这样就造成了递归调用。
# 意味调用``self.__setattrr__('name', value)``,每次方法会调用自己,造成程序崩溃。
# correct
def __setattr__(self, name, value):
self.__dict__[name] = value # 给类中的属性分配值
# 定制特有属性
-
__delattr__:
删除一个属性,实现时要防止无限递归发生
创建自定义容器
Python
容器类型:
可变类型: list
, dict
等
不可变类型: string
,tuple
等
-
__len__(self)
:返回容器长度。 -
__getitem__(self, key)
:当定义某一项被访问时,使用self[key]
所产生的行为。 -
__setitem__(self, key, value)
:执行self[key] = value
,调用该方法。 -
__delitem__(self)
:定义删除一个项目时的行为,如del self[key]
-
__iter__(self)
:返回一个容器迭代器。 -
__reversed__(self)
:实现当reversed()
被调用时的行为。 -
__contains__(self, item)
:定义调用in
和not in
来测试成员是否在的时候产生的行为。 -
__missing__(self, key)
:dict
类型会有该方法,它定义了key
如果在容器中找不到时触发的行为。
class FunctionalList:
'''实现内置list功能,并丰富一些其他用法'''
def __init__(self, values=None):
if values is None:
self.values = []
else:
self.values = values
def __len__(self):
return len(self.values)
def __getitem__(self, key):
return self.values[key]
def __setitem__(self, key, value):
return self.values[key] = value
def __delitem__(self, key):
del self.values[key]
def __iter__(self):
return iter(self.values)
def __reversed__(self):
return FunctionalList(reversed(self.values))
def append(self, value):
self.values.append(value)
def head(self):
return self.values[0]
def tail(self):
return self.values[1:]
def init(self):
return self.values[:-1]
def last(self):
return self.values[-1]
def drop(self, n):
return self.values[n:]
def task(self, n):
return self.values[:n]
反射
控制怎么使用内置函数 isinstance()和issubclass()方法,反射定义魔术方法:
-
__instancecheck__(self, instance)
:
检查一个实例是不是你定义类的实例 -
__subclasscheck__(self, subclass)
:
检查一个类是不是你定义类的子类
可调用对象
特殊的魔术方法可以让类的实例的行为表现像函数一样,可以调用它们,将一个函数当做参数传递到另外一个函数中等。
-
__call__(self, [args,...]):
允许一个类的实例像函数一样被调用。这意味着x()
与x.__call__()
是相同的。__call__
的参数可变,可以定义它为你想要的函数。
__call__
在那些类的实例经常改变状态的时候非常有效。调用这个实例是一种改变这个对象状态的直接和优雅的做法。
class Entity:
'''调用实体来改变实体的位置'''
def __init__(self, size, x, y):
self.x, self.y = x, y
self.size = size
def __call__(self, x, y):
'''改变实体位置'''
self.x, self.y = x, y
上下文管理器
with
声明的代码段中,可以做一些对象的开始操作和退出操作,还能对异常进行处理。需要实现两个魔术方法__enter__
和__exit__
:
-
__enter__(self):
定义了当声明with
语句的时候,会话管理器在块被初始创建时产生的行为,__enter__
的返回值与with
语句的目标或者as
后的名字绑定。 -
__exit__(self):
定义了一个代码块被执行或者终止后,会话管理器应该做什么。可以被用来处理异常,执行清理工作或做一些代码块执行完毕后的日常。如果代码块执行成功,exception_type
,exception_value
和traceback
将为None
。否则你可以选择处理这个异常,或者直接交给客户处理。如果你想处理这个异常,请确保__exit__
所在的语句结束后返回True
。如果你想让异常会话被管理器处理,那就让其产生异常。
创建对象描述器
描述器是通过获取、设置及删除的时候访问的类。描述器并不是独立的,它意味着被一个类所有者持有。当创建面向对象的数据库或者类,里面含有相互依赖的属性时,描述器将会非常有用。一种典型的用法用不同的单位表示数值,或者某个数据的附加属性。
一个描述器类至少应该包括:__get__
,__set__
,__delete__
方法被实现:
__get__(self, instance, owner):
定义描述器的值被取得时候的行为。instance
是拥有该描述器对象的实例,owner
是拥有者本身。__set__(self, instance, value):
定义描述器的值被改变时候的行为。instance
是拥有该描述器对象的实例,value
是要设置的值。__delete__(self, instance):
定义了描述器值被删除时的行为。instance
是拥有该描述器对象的实例
描述器的实例,单位转换
class Meter(object):
"""单位'米'的描述器"""
def __init__(self, value=0.0):
self.value = float(value)
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = float(value)
class Foot(object):
"""单位'尺'的描述器"""
def __get__(self, instance, owner):
return instance.meter * 3.2808
def __set__(self, instance, value):
instance.meter = float(value) / 3.2808
class Distance(object):
"""用米和英寸表示两个描述器之间的距离"""
meter = Meter(10)
foot = Foot()
拷贝
__copy__(self)
:
调用copy.copy()
时产生的行为,返回你的对象的浅拷贝__deepcopy__(self memdict={})
:
调用copy.deepcopy()
时产生的行为,返回你的对象的深拷贝。memdict
是对之前被拷贝对象的一个缓存----这优化了拷贝过程并且阻止了对递归数据结构拷贝时的无限递归。当你想要进行单独的属性进行拷贝时,调用copy.deepcopy()
,并用memdict
为第一个参数