特殊方法:
又名魔术方法,所有双下划线开头双下划线结尾的方法
- 构造函数,析构函数,__call__
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class Meta(type):
def __new__(meta_class, name, bases, attrs):
# 这里主要是为了获取name, bases, attrs这三个东西,便于做进一步的处理
cls = super(Meta, meta_class).__new__(meta_class, name, bases, attrs)
print cls #
print meta_class #
print name # FOO
print bases # (,)
print attrs # {'demo': , '__module__': '__main__', '__metaclass__': , '__new__': }
# 可以在这里做很多 针对cls的操作
cls.a = 'herehere'
return cls
def __init__(cls, name, bases, attrs):
print cls, name, bases, attrs
def __call__(cls, *args, **kwargs):
self = cls.__new__(cls, *args, **kwargs)
if isinstance(self, cls):
self.__init__(*args, **kwargs)
return self
class Base(object):
pass
class FOO(Base):
__metaclass__ = Meta
def __new__(cls, *args, **kwargs):
# 返回值是FOO的实例,例如,return 'aaa',那么print FOO(1, 2, 3)的输出就是aaa
print args
return object.__new__(cls)
def __init__(self, *args, **kwargs):
pass
def demo(self):
pass
def __del__(self):
pass
foo = FOO(1, 2, 3)
print foo.a # herehere
- 属性控制
__setattr__
__getattr__
__delattr__
__getattribute__ :本方法定义了对象对属性的获取顺序。
def __setattr__(self, name, value):
self.name = value
#每当属性被赋值的时候, "__setattr__()" 会被调用,这样就造成了递归调用。
#这意味这会调用 "self.__setattr__('name', value)" ,每次方法会调用自己。这样会造成程序崩溃。
def __setattr__(self, name, value):
self.__dict__[name] = value #给类中的属性名分配值
#定制特有属性
- 创建定制的序列,(可迭代对象等)
现在我们开始讲如何在Python中创建定制的序列,这个时候该讲一讲协议。
协议(Protocols)与其他语言中的接口很相似。它给你很多你必须定义的方法。然而在Python中的协议是很不正式的,不需要明确声明实现。事实上,他们更像一种指南。
a) 实现不可变容器,你只能定义 __len__ 和 __getitem__
b) 可变容器协议则需要所有不可变容器的所有另外还需要 __setitem__ 和 __delitem__。
c) 如果你希望你的对象是可迭代的话(可迭代对象),你需要定义 __iter__会返回一个迭代器。
d) 迭代器必须遵循迭代器协议,需要有 __iter__ (返回它本身) 和 __next__ 。
__getitem__(self, key) 定义当一个条目被访问时,使用符号 self[key]
__setitem__(self, key, value) 定义当一个条目被赋值时的行为,使用 self[key] = value
__delitem__(self, key) 定义当一个条目被删除时的行为(比如 del self[key])
__iter__(self) 返回一个容器的迭代器,尤其是当内置的 iter() 方法被调用的时候,或者当使用 for x in container 方式循环的时候。迭代器是他们本身的对象,他们必须定义返回 self 的 __iter__ 方法
__reversed__(self) 实现当 reversed() 被调用时的行为
__contains__(self, item) 当调用 in 和 not in 来测试成员是否存在时候 __contains__ 被定义,当 __contains__ 没有被定义的时候,Python会迭代这个序列并且当找到需要的值时会返回 True 。__concat__(self, other) 和 + 操作符相关
- 上下文管理器(会话管理)
with 管理的上下文实际上就是Closer,Closer是一个类(也是命名空间),这个命名空间提供了两个大门,一个前门(enter),一个后门exit。上下文管理器可以自动捕获异常,除此之外,在没有别的特别的地方了。
class Closer(object):
def __init__(self, obj):
self.obj = obj #'obj'
def __enter__(self):
return self.obj #conn
def __exit__(self, exception_type, exception_val, trace):
try:
print 'im here'
print exception_type, exception_val, trace
except AttributeError:
print 'Not closable.'
return True #处理conn.dir()引起的异常,如果返回True,并不会将异常向上级发送。
with Closer('obj') as conn:
print conn
raise Exception('exception info')
print conn
print 'out of context management'
- 描述符
描述符能够让一个属性变成一个方法,使python对属性的读写有更多的逻辑控制,描述符的优先级非常高~
python对属性的搜索优先级
class Meter(object):
'''Descriptor for a meter.'''
def __init__(self, value=3):
self.value = float(value)
def __get__(self, instance, owner):
print instance.attr_demo # instance_attr
print owner.attr_demo # class_attr
return self.value
def __set__(self, instance, value):
self.value = float(value)
class Foot(object):
'''Descriptor for a foot.'''
def __get__(self, instance, owner):
return instance.meter * 3.2808
def __set__(self, instance, value):
instance.meter = float(value) / 3.2808
class Distance(object):
'''Class to represent distance holding two descriptors for feet and
meters.'''
attr_demo = 'class_attr'
meter = Meter()
foot = Foot()
distance_instance_demo = Distance()
distance_instance_demo.attr_demo = 'instance_attr'
print distance_instance_demo.meter # 3.0
print distance_instance_demo.foot # 9.8424
- __index__
class IndexHash(object):
def __index__(self):
return 1
index_hash = IndexHash()
list_demo = ['abc', 'def', 'ghi']
print list_demo[index_hash] # 'def'
魔术方法 | 调用方式 | 解释 |
---|---|---|
new(cls [,...]) | instance = MyClass(arg1, arg2) | new 在创建实例的时候被调用 |
init(self [,...]) | instance = MyClass(arg1, arg2) | init 在创建实例的时候被调用 |
cmp(self, other) | self == other, self > other, 等。 | 在比较的时候调用 |
pos(self) | +self | 一元加运算符 |
neg(self) | -self | 一元减运算符 |
invert(self) | ~self | 取反运算符 |
index(self) | x[self] | 对象被作为索引使用的时候 |
nonzero(self) | bool(self) | 对象的布尔值 |
getattr(self, name) | self.name # name 不存在 | 访问一个不存在的属性时 |
setattr(self, name, val) | self.name = val | 对一个属性赋值时 |
delattr(self, name) | del self.name | 删除一个属性时 |
__getattribute(self, name) | self.name | 访问任何属性时 |
getitem(self, key) | self[key] | 使用索引访问元素时 |
setitem(self, key, val) | self[key] = val | 对某个索引值赋值时 |
delitem(self, key) | del self[key] | 删除某个索引值时 |
iter(self) | for x in self | 迭代时 |
contains(self, value) | value in self, value not in self | 使用 in 操作测试关系时 |
concat(self, value) | self + other | 连接两个对象时 |
call(self [,...]) | self(args) | “调用”对象时 |
enter(self) | with self as x: | with 语句环境管理 |
exit(self, exc, val, trace) | with self as x: | with 语句环境管理 |
getstate(self) | pickle.dump(pkl_file, self) | 序列化 |
setstate(self) | data = pickle.load(pkl_file) | 序列化 |