1、__ new__, __ init__, __ call__
__ new__(cls, *args, **kwargs) 创建对象时调用,返回当前对象的一个实例;注意:这里的第一个参数是cls即class本身
__ init__(self, *args, **kwargs) 创建完对象后调用,对当前对象的实例的一些初始化,无返回值,即在调用__new__之后,根据返回的实例初始化;注意,这里的第一个参数是self即对象本身
__ call__(self, *args, **kwargs) 如果类实现了这个方法,相当于把这个类型的对象当作函数来使用,相当于 重载了括号运算符
继承自object的新式类才有__ new__
__ new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
__ new__必须要有返回值,返回实例化出来的实例,这点在自己实现_ new__时要特别注意,可以return父类__ new__出来的实例,或者直接是object的 _new__出来的实例
__ init__有一个参数self,就是这个 __ new__返回的实例,__ init__在__ new__的基础上可以完成一些其它初始化的动作,__ init__不需要返回值
若_ _new__没有正确返回当前类cls的实例,那__ init__是不会被调用的,即使是父类的实例也不行
http://www.cnblogs.com/ifantastic/p/3175735.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class Foo(object): def __init__(self, *args, **kwargs): ... def __new__(cls, *args, **kwargs): return object.__new__(cls, *args, **kwargs) # 以上return等同于 # return object.__new__(Foo, *args, **kwargs) # return Stranger.__new__(cls, *args, **kwargs) # return Child.__new__(cls, *args, **kwargs) class Child(Foo): def __new__(cls, *args, **kwargs): return object.__new__(cls, *args, **kwargs) # 如果Child中没有定义__new__()方法,那么会自动调用其父类的__new__()方法来制造实例,即 Foo.__new__(cls, *args, **kwargs)。 # 在任何新式类的__new__()方法,不能调用自身的__new__()来制造实例,因为这会造成死循环。因此必须避免类似以下的写法: # 在Foo中避免:return Foo.__new__(cls, *args, **kwargs)或return cls.__new__(cls, *args, **kwargs)。Child同理。 # 使用object或者没有血缘关系的新式类的__new__()是安全的,但是如果是在有继承关系的两个类之间,应避免互调造成死循环,例如:(Foo)return Child.__new__(cls), (Child)return Foo.__new__(cls)。 class Stranger(object): ... # 在制造Stranger实例时,会自动调用 object.__new__(cls) |
1 2 |
也可以这么调用 new_class = super(RenameMethodsBase, cls).__new__(cls, name, bases, attrs) |
通常来说,新式类开始实例化时,new()方法会返回cls(cls指代当前类)的实例,然后该类的init()方法作为构造方法会接收这个实例(即self)作为自己的第一个参数,然后依次传入new()方法中接收的位置参数和命名参数。
注意:如果new()没有返回cls(即当前类)的实例,那么当前类的init()方法是不会被调用的。如果new()返回其他类(新式类或经典类均可)的实例,那么只会调用被返回的那个类的构造方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Foo(object): def __init__(self, *args, **kwargs): ... def __new__(cls, *args, **kwargs): return object.__new__(Stranger, *args, **kwargs) class Stranger(object): ... foo = Foo() print type(foo) # 打印的结果显示foo其实是Stranger类的实例。 # 因此可以这么描述__new__()和__ini__()的区别,在新式类中__new__()才是真正的实例化方法,为类提供外壳制造出实例框架,然后调用该框架内的构造方法__init__()使其丰满。 # 如果以建房子做比喻,__new__()方法负责开发地皮,打下地基,并将原料存放在工地。而__init__()方法负责从工地取材料建造出地皮开发招标书中规定的大楼,__init__()负责大楼的细节设计,建造,装修使其可交付给客户。 |
2、__ del__
它不实现语句 del x (以上代码将不会翻译为 x.__ del__() )。它定义的是当一个对象进行垃圾回收时候的行为。当一个对象在删除的时需要更多的清洁工作的时候此方法会很有用,比如套接字对象或者是文件对象。注意,如果解释器退出的时候对象还存存在,就不能保证 __ del__ 能够被执行
1 2 3 4 5 6 7 8 9 10 11 12 |
from os.path import join class FileObject: '''给文件对象进行包装从而确认在删除时文件流关闭''' def __init__(self, filepath='~', filename='sample.txt'): #读写模式打开一个文件 self.file = open(join(filepath, filename), 'r+') def __del__(self): self.file.close() del self.file |
3、用于比较的魔术方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
Python对实现对象的比较,使用魔术方法进行了大的逆转,使他们非常直观而不是笨拙的方法调用。 而且还提供了一种方法可以重写Python对对象比较的默认行为(通过引用)。以下是这些方法和他们的作用。 __cmp__(self, other) __cmp__ 是最基本的用于比较的魔术方法。它实际上实现了所有的比较符号(<,==,!=,etc.),但是它的表现并不会总是如你所愿(比如,当一个实例与另一个实例相等是通过一个规则来判断,而一个实例大于另外一个实例是通过另外一个规则来判断)。 如果 self < other 的话 __cmp__ 应该返回一个负数,当 self == other 的时候会返回0 ,而当 self > other 的时候会返回正数。通常最好的一种方式是去分别定义每一个比较符号而不是一次性将他们都定义。 但是 __cmp__ 方法是你想要实现所有的比较符号而一个保持清楚明白的一个好的方法。 __eq__(self, other) 定义了等号的行为, == 。 __ne__(self, other) 定义了不等号的行为, != 。 __lt__(self, other) 定义了小于号的行为, < 。 __gt__(self, other) 定义了大于等于号的行为, >= 。 class Word(str): '''存储单词的类,定义比较单词的几种方法''' def __new__(cls, word): # 注意我们必须要用到__new__方法,因为str是不可变类型 # 所以我们必须在创建的时候将它初始化 if ' ' in word: print "Value contains spaces. Truncating to first space." word = word[:word.index(' ')] #单词是第一个空格之前的所有字符 return str.__new__(cls, word) def __gt__(self, other): return len(self) > len(other) def __lt__(self, other): return len(self) < len(other) def __ge__(self, other): return len(self) >= len(other) def __le__(self, other): return len(self) <= len(other) |
http://pycoders-weekly-chinese.readthedocs.org/en/latest/issue6/a-guid…