资讯专栏INFORMATION COLUMN

python中的魔术方法__

SegmentFault / 1247人阅读

摘要:在任何新式类的方法,不能调用自身的来制造实例,因为这会造成死循环。因此必须避免类似以下的写法在中避免或。注意如果没有返回即当前类的实例,那么当前类的方法是不会被调用的。是最基本的用于比较的魔术方法。

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

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)
也可以这么调用
new_class = super(RenameMethodsBase, cls).__new__(cls, name, bases, attrs)
  

通常来说,新式类开始实例化时,new()方法会返回cls(cls指代当前类)的实例,然后该类的init()方法作为构造方法会接收这个实例(即self)作为自己的第一个参数,然后依次传入new()方法中接收的位置参数和命名参数。

注意:如果new()没有返回cls(即当前类)的实例,那么当前类的init()方法是不会被调用的。如果new()返回其他类(新式类或经典类均可)的实例,那么只会调用被返回的那个类的构造方法。

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__ 能够被执行

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、用于比较的魔术方法

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...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37574.html

相关文章

  • 介绍Python魔术方法 - Magic Method

    摘要:所以准确来说是和共同构成了构造函数是用来创建类并返回这个类的实例而只是将传入的参数来初始化该实例在创建一个实例的过程中必定会被调用但就不一定,比如通过的方式反序列化一个实例时就不会调用。 前言 在Python中,所有以__双下划线包起来的方法,都统称为魔术方法。比如我们接触最多的__init__. 有些魔术方法,我们可能以后一辈子都不会再遇到了,这里也就只是简单介绍下; 而有些魔术方法...

    animabear 评论0 收藏0
  • python学习笔记-魔术方法,让自定义类更像内置类型

    摘要:的魔术方法是中那些预定义的像类型的函数。使用的魔术方法的最大优势在于提供了简单的方法让对象可以表现得像内置类型一样。廖雪峰老师教程里写的是方法,不知道为啥。 Python的魔术方法是Python中那些预定义的像__XXX__类型的函数。使用Python的魔术方法的最大优势在于python提供了简单的方法让对象可以表现得像内置类型一样。 __str__函数 __str__函数用于处理打印...

    changfeng1050 评论0 收藏0
  • Python魔术方法做出更好的正则表达式 API

    摘要:注原文地址为我的一个同事提到他错过了的正则表达式的语法糖。首先,从正则表达式检索捕捉组需要两个步骤。语法糖为了好玩,我把一个小小的增加了一些语法糖的正则表达式库的帮助类放在一起。调用将调用类的方法。 注:原文地址为 Playing with Python Magic Methods to make a nicer Regex API 我的一个同事提到,他错过了 Ruby 的正...

    MangoGoing 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<