python魔法方法-比较相关

  在python2.x的版本中,支持不同类型的比较,其比较原则如下:

内置类型:

  1.同一类型: 1.1)数字类型:包含int、float、long、complex、bool(bool类型是int的子类,且True=1, False=0)。就按照数字的大小进行比较,例如:

          1.2)非数字类型:1.2.1)如果类型中定义了如__cmp__、__gt__等魔法方法,就按照其魔法方法的返回值进行比较,具体如何就是这篇文章接下来要讨论的内容。

                  1.2.2)如果没有定义上述的魔法方法,就按照 id 函数的返回值进行比较,由于 id 函数返回的是 int,所以返回值按照数字的规则进行比较。

  2.不同类型:2.1)如果比较的对象中含有数字类型,例如:int 和 str 进行比较。数字类型将小于其他任何类型,也就是说“数字类型是最小的”(不包括None,None比数字类型还小,所以应该说是None最小,但很少会使用None类型比较,所以这里忽略None,得出数字类型最小的结论)。

        2.2)如果比较的对象中不含有数字类型,例如 dict 和 str 进行比较。那么就按类名进行比较,所以 {} < ‘‘ 相当于 ‘dict‘ < ‘str‘ ,即将类名转换为字符串,然后按字符串的原则进行比较。

这里有几点要补充的:

  虽然内置类型基本都实现了__eq__、__ge__、__gt__等内置方法,但是这里有必要对相同类型实例直接的比较进行总结说明:

1.序列的比较:

  序列的比较是按照索引顺序取出元素进行比较,如果不两个系列不等长,则可以看作是在短的序列后面填充 None ,直到两个序列等长。

  在 tuple 和 list 的讨论中,我使用了打擂台的比喻。两个比较的序列相当于按照索引顺序派出选手,比赛采用的是残酷的赛制,一旦某个选手失败,那么那个队伍就会输掉。也就是说一旦某个元素小于对面,那么整个序列都会小于另一个序列。

  当然这里说的是同一类型的序列,例如 str、list、tuple之间的比较是属于不同内置类型的比较,按照上面的原则,就是按照类名进行比较。所以这里讨论的是 str和 str 的比较;list 和 list 的比较;tuple 和 tuple的比较。

  str 和 str 之间的比较:首先按照序列顺序排出元素,而 str 中的元素就是单个字符,然后字符之间的比较是通过将其转换为 acsll 码后进行数字之间的比较的。python 中提供了一个内置的函数 ord 来进行这项工作:

  还有一个反函数 chr 用来将数字转换成字符:

  所以,当字符串 ‘abc‘ 和字符串 ‘abe‘ 进行比较时,前两个字符相等,而 ‘e‘ > ‘c‘ ,所以 ‘abe‘ > ‘abc‘。

  如果两者不等长时,例如:‘abc‘ 和 ‘ab‘ 进行比较,前两字符相等,而 ‘c‘ 相对于和 None 比,None又最小,所以 ‘abc‘  > ‘ab‘ 。

  其他序列也遵循这个逐项比较的原则,例如:[1, 2, 3] 和 [1, [2], 3] 比较时,第一个元素相等,所以比第二个元素。第二元素是不同类型的,其中一个是数字,数字除None外最小,所以第二个列表比较大。如果一直比较下去都相等的话,那么就判断两个元素相等(== )。但是这并不意味着两个元素是同一个对象,所以 is 判断不一定为 True。

  另外,中文是按照编码的字符串进行比较的,例如:

  ‘d‘ > ‘b‘ 所以 ‘一‘ > ‘二‘。但字符串的编码是会根据编码声明而改变的,例如 # coding: utf-8 和 # coding= gbk 的字符串编码就不一样,所以比较会有差异性。但是也很少会进行中文之间的比较。

  集合和序列的比较方法类似。

2.字典间的比较:

  字典其实也类似于序列,也是逐个比较,但字典比较的是不是值,而且字典是无序的,所以比较的顺序难以预测,所以无论如何,不建议字典间的比较。

版本差异:

  由于不同内置类型之间的比较不符合人的直觉,而且行为怪异,难以估计。所以python3.x中取消了不同内置类型之间比较的支持,例如:在python3.x中进行 int 和 str 之间的比较时会直接抛出异常。



自定义的类:

  1.继承自基本类型且没有重写相关的魔法方法,那么就按照上面内置类型的原则进行比较。

  2.自定义的类,但没有重写相关魔法方法。那么 新式类 > 经典类;新式类之间按类名进行比较;经典类之间按 id 函数的返回值进行比较。

  3.只要重写了相应的魔法方法,那么就按照魔法方法的返回值作为结果。不管是否继承自基本类型。

相关魔法方法:

   __cmp__(self, other) :对应于python的内置函数 cmp ,在self > other 时应该返回 正整数;self == other时,返回 0;当self < other时应该返回一个 负整数。(这个方法因为和下面的方法存在冗余,所以在python3.x中被删除了。)

例子:

class Foo(str):
    def __new__(cls, word):
        return str.__new__(cls, word)

    def __cmp__(self, other):
        if (‘scolia‘ in self) and (‘scolia‘ in other):
            return 0
        elif ‘scolia‘ in self:
            return 1
        else:
            return -1

a = Foo(‘scolia‘)
b = Foo(‘scolia123‘)
c = Foo(‘good‘)
d = Foo(‘Good‘)
print cmp(a, b)
print cmp(b, c)
print cmp(c, d)

  在这个例子中,我定义凡是两个字符串中都有子串‘scolia‘的,都返回0;当个只有一个有,且有的那个作为第一个参数时,返回1;两个都没有,不管是什么都返回-1。

  也就是说cmp函数的第一个参数就是 self ,第二个参数就是 other。

  当然 cmp 还有一个隐藏特性, 当两个参数为同一对象的时候,直接返回0而不管内部的__cmp__逻辑如果,例如:

c = Foo(‘good‘)
d = c
print cmp(c, d)

  本来按照自己写的代码的逻辑的话,c 和 d 都不含字串 ‘scolia‘ ,应该返回-1才对,但是实际上得到的却是0。说明cmp函数对于同一对象是直接给出结果而不理魔法方法的。

  • __eq__(self, other)
  • 定义相等符号的行为,==
  • __ne__(self,other)
  • 定义不等符号的行为,!=
  • __lt__(self,other)
  • 定义小于符号的行为,<
  • __gt__(self,other)
  • 定义大于符号的行为,>
  • __le__(self,other)
  • 定义小于等于符号的行为,<=
  • __ge__(self,other)
  • 定义大于等于符号的行为,>=

  以上魔法方法都必须返回一个布尔值

例如:

class Foo(str):
    def __new__(cls, word):
        return str.__new__(cls, word)

    def __eq__(self, other):
        if (‘scolia‘ in self ) and (‘scolia‘ in other):
            return True
        else:
            return False

a = Foo(‘scolia‘)
b = Foo(‘scolia123‘)
print a == b

  所以,这些魔法方法其实就是重载了相应的符号而已,例如这里的 == ,左边的相当于 self,右边的相当于 other。你可以根据自己的需要进行逻辑编排。

又例如:

class Foo(str):
    def __new__(cls, word):
        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)

  这里重载了多个比较符,是核心是按照字符串的长度进行比较,越长的越大。这里看似返回的是一个表达式,但是函数在真正返回的时候会将这个表达式计算出来,也就是说最终返回的其实还是布尔值。

  而没有重载的比较符,如这里没有重载 __eq__ 即 == ,将自动调用其父类的方法,这也很符合我们继承的概念。

如果和基本类型比较呢:

class Foo(str):
    def __new__(cls, word):
        return str.__new__(cls, word)

    def __eq__(self, other):
        if (‘scolia‘ in self ) and (‘scolia‘ in other):
            return True
        else:
            return False

b = Foo(‘scolia‘)
a = ‘scolia123‘
print a == b
print b == a

  貌似是以我们自己写的方法为准,不管 == 两边的顺序如何。

如果两个自定义的类冲突呢:

class Foo(str):
    def __new__(cls, word):
        return str.__new__(cls, word)

    def __eq__(self, other):
        if (‘scolia‘ in self ) and (‘scolia‘ in other):
            return True
        else:
            return False

class Boo(str):
    def __new__(cls, word):
        return str.__new__(cls, word)

    def __eq__(self, other):
        if (‘scolia‘ in self ) and (‘scolia‘ in other):
            return False
        else:
            return True

a = Foo(‘scolia‘)
b = Boo(‘scolia‘)
print a == b
print b == a

  此时,谁在 == 号的左边,就运用谁的规则。



  关于比较的魔法方法就讨论到这里,欢迎大家交流。

  相关的参考资料:戳这里

时间: 2024-10-26 11:59:16

python魔法方法-比较相关的相关文章

python 魔法方法,属性,迭代

9.2 构造方法 python 中也属于自己的构造函数和析构函数, class fibs: def __init__(self): self.a = 0 self.b = 1 def next(self): self.a,self.b = self.b,self.a+self.b return self.a def __iter__(self): return self fib = fibs() for i in fib: if i>1000: print i break 其中的__init__

Python 魔法方法~~

网友写的python魔法方法详情 :详情 魔法方法 含义   基本的魔法方法 __new__(cls[, ...]) 1. __new__ 是在一个对象实例化的时候所调用的第一个方法2. 它的第一个参数是这个类,其他的参数是用来直接传递给 __init__ 方法3. __new__ 决定是否要使用该 __init__ 方法,因为 __new__ 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 __new__ 没有返回实例对象,则 __init__ 不会被调用4. __ne

Python魔法方法总结及注意事项

1.何为魔法方法: Python中,一定要区分开函数和方法的含义: 1.函数:类外部定义的,跟类没有直接关系的:形式: def func(*argv): 2.方法:class内部定义的函数(对象的方法也可以认为是属性):分为两种: ① python自动产生的(魔法方法):一般形式为 __func__(),python会在对应的时机自动调用该函数: ② 人为自定义的方法:一般和普通函数没有区别,只是定义在了class中而已 3.方法与函数的区别: 方法可认为是函数的特殊情况: ① 方法定义在cla

python魔法方法-属性转换和类的表示

类型转换魔法 类型转换魔法其实就是实现了str.int等工厂函数的结果,通常这些函数还有类型转换的功能,下面是一些相关的魔法方法: __int__(self) 转换成整型,对应int函数. __long__(self) 转换成长整型,对应long函数. __float__(self) 转换成浮点型,对应float函数. __complex__(self) 转换成 复数型,对应complex函数. __oct__(self) 转换成八进制,对应oct函数. __hex__(self) 转换成十六进

python魔法方法-自定义序列

自定义序列的相关魔法方法允许我们自己创建的类拥有序列的特性,让其使用起来就像 python 的内置序列(dict,tuple,list,string等). 如果要实现这个功能,就要遵循 python 的相关的协议.所谓的协议就是一些约定内容.例如,如果要将一个类要实现迭代,就必须实现两个魔法方法:__iter__.next(python3.x中为__new__).__iter__应该返回一个对象,这个对象必须实现 next 方法,通常返回的是 self 本身.而 next 方法必须在每次调用的时

python魔法方法

Python 魔术方法指南 入门 构造和初始化 构造定制类 用于比较的魔术方法 用于数值处理的魔术方法 表现你的类 控制属性访问 创建定制序列 反射 可以调用的对象 会话管理器 创建描述器对象 持久化对象 总结 附录 介绍 此教程为我的数篇文章中的一个重点.主题是魔术方法. 什么是魔术方法?他们是面向对象的Python的一切.他们是可以给你的类增加”magic”的特殊方法.他们总是被双下划线所包围(e.g. __init__ 或者 __lt__).然而他们的文档却远没有提供应该有的内容.Pyth

python魔法方法、构造函数、序列与映射、迭代器、生成器

在Python中,所有以__双下划线包起来的方法,都统称为"魔术方法".比如我们接触最多的__init__,魔法方法也就是具有特殊功能的方法. 构造函数 构造函数不同于普通方法,将在对象创建后自动调用它们.也就是在对象创建完成后,自动会调用__init__方法来初始化. 创建一个构造方法 构造方法传参 >>> class FooBar: def __init__(self,value=42): #默认参数 self.somevar = value >>&g

python魔法方法详解

文章来源:http://blog.csdn.net/koko66/article/details/42709279 据说,Python 的对象天生拥有一些神奇的方法,它们总被双下划线所包围,他们是面向对象的 Python 的一切. 他们是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一切都是自动发生的. Python 的魔术方法非常强大,然而随之而来的则是责任.了解正确的方法去使

python魔法方法-反射运算和增量运算

反射运算 什么是反射运算符,其实就是反转了两个对象,下面先看一个普通运行符的实现: class Foo(object): def __init__(self, x): self.x = x def __add__(self, other): return 'Foo:%s + %s' % (self.x, other.x) class Boo(object): def __init__(self, x): self.x = x def __add__(self, other): return 'B