Python运算符重载详解及实例代码

Python运算符重载

Python语言提供了运算符重载功能,增强了语言的灵活性,这一点与C++有点类似又有些不同。鉴于它的特殊性,今天就来讨论一下Python运算符重载。

Python语言本身提供了很多魔法方法,它的运算符重载就是通过重写这些Python内置魔法方法实现的。这些魔法方法都是以双下划线开头和结尾的,类似于__X__的形式,python通过这种特殊的命名方式来拦截操作符,以实现重载。当Python的内置操作运用于类对象时,Python会去搜索并调用对象中指定的方法完成操作。

类可以重载加减运算、打印、函数调用、索引等内置运算,运算符重载使我们的对象的行为与内置对象的一样。Python在调用操作符时会自动调用这样的方法,例如,如果类实现了__add__方法,当类的对象出现在+运算符中时会调用这个方法。

常见运算符重载方法


方法名


重载说明


运算符调用方式


__init__


构造函数


对象创建: X = Class(args)


__del__


析构函数


X对象收回


__add__/__sub__


加减运算


X+Y, X+=Y/X-Y, X-=Y


__or__


运算符|


X|Y, X|=Y


_repr__/__str__


打印/转换


print(X)、repr(X)/str(X)


__call__


函数调用


X(*args, **kwargs)


__getattr__


属性引用


X.undefined


__setattr__


属性赋值


X.any=value


__delattr__


属性删除


del X.any


__getattribute__


属性获取


X.any


__getitem__


索引运算


X[key],X[i:j]


__setitem__


索引赋值


X[key],X[i:j]=sequence


__delitem__


索引和分片删除


del X[key],del X[i:j]


__len__


长度


len(X)


__bool__


布尔测试


bool(X)


__lt__, __gt__,

__le__, __ge__,

__eq__, __ne__


特定的比较


依次为X<Y,X>Y,X<=Y,X>=Y,

X==Y,X!=Y

注释:(lt: less than, gt: greater than,

le: less equal, ge: greater equal,

eq: equal, ne: not equal


__radd__


右侧加法


other+X


__iadd__


实地(增强的)加法


X+=Y(or else __add__)


__iter__, __next__


迭代


I=iter(X), next()


__contains__


成员关系测试


item in X(X为任何可迭代对象)


__index__


整数值


hex(X), bin(X),  oct(X)


__enter__, __exit__


环境管理器


with obj as var:


__get__, __set__,

__delete__


描述符属性


X.attr, X.attr=value, del X.attr


__new__


创建


在__init__之前创建对象

下面对常用的运算符方法的使用进行一下介绍。

构造函数和析构函数:__init__和__del__

它们的主要作用是进行对象的创建和回收,当实例创建时,就会调用__init__构造方法。当实例对象被收回时,析构函数__del__会自动执行。

>>> class Human():
...   def __init__(self, n):
...     self.name = n
...       print("__init__ ",self.name)
...   def __del__(self):
...     print("__del__")
...
>>> h = Human('Tim')
__init__ Tim
>>> h = 'a'
__del__

加减运算:__add__和__sub__

重载这两个方法就可以在普通的对象上添加+-运算符操作。下面的代码演示了如何使用+-运算符,如果将代码中的__sub__方法去掉,再调用减号运算符就会出错。

>>> class Computation():
...   def __init__(self,value):
...     self.value = value
...   def __add__(self,other):
...     return self.value + other
...   def __sub__(self,other):
...     return self.value - other
...
>>> c = Computation(5)
>>> c + 5
10
>>> c - 3
2

对象的字符串表达形式:__repr__和__str__

这两个方法都是用来表示对象的字符串表达形式:print()、str()方法会调用到__str__方法,print()、str()和repr()方法会调用__repr__方法。从下面的例子可以看出,当两个方法同时定义时,Python会优先搜索并调用__str__方法。

>>> class Str(object):
...   def __str__(self):
...     return "__str__ called"
...   def __repr__(self):
...     return "__repr__ called"
...
>>> s = Str()
>>> print(s)
__str__ called
>>> repr(s)
'__repr__ called'
>>> str(s)
'__str__ called'

索引取值和赋值:__getitem__, __setitem__

通过实现这两个方法,可以通过诸如 X[i] 的形式对对象进行取值和赋值,还可以对对象使用切片操作。

>>> class Indexer:
  data = [1,2,3,4,5,6]
  def __getitem__(self,index):
    return self.data[index]
  def __setitem__(self,k,v):
    self.data[k] = v
    print(self.data)
>>> i = Indexer()
>>> i[0]
1
>>> i[1:4]
[2, 3, 4]
>>> i[0]=10
[10, 2, 3, 4, 5, 6]

设置和访问属性:__getattr__、__setattr__

我们可以通过重载__getattr__和__setattr__来拦截对对象成员的访问。__getattr__在访问对象中不存在的成员时会自动调用。__setattr__方法用于在初始化对象成员的时候调用,即在设置__dict__的item时就会调用__setattr__方法。具体例子如下:

class A():
  def __init__(self,ax,bx):
    self.a = ax
    self.b = bx
  def f(self):
    print (self.__dict__)
  def __getattr__(self,name):
    print ("__getattr__")
  def __setattr__(self,name,value):
    print ("__setattr__")
    self.__dict__[name] = value 

a = A(1,2)
a.f()
a.x
a.x = 3
a.f()

上面代码的运行结果如下,从结果可以看出,访问不存在的变量x时会调用__getattr__方法;当__init__被调用的时候,赋值运算也会调用__setattr__方法。

__setattr__
__setattr__
{'a': 1, 'b': 2}
__getattr__
__setattr__
{'a': 1, 'x': 3, 'b': 2}

迭代器对象: __iter__,  __next__

Python中的迭代,可以直接通过重载__getitem__方法来实现,看下面的例子。

>>> class Indexer:
...   data = [1,2,3,4,5,6]
...   def __getitem__(self,index):
...       return self.data[index]
...
>>> x = Indexer()
>>> for item in x:
...   print(item)
...
1
2
3
4
5
6

通过上面的方法是可以实现迭代,但并不是最好的方式。Python的迭代操作会优先尝试调用__iter__方法,再尝试__getitem__。迭代环境是通过iter去尝试寻找__iter__方法来实现,而这种方法返回一个迭代器对象。如果这个方法已经提供,Python会重复调用迭代器对象的next()方法,直到发生StopIteration异常。如果没有找到__iter__,Python才会尝试使用__getitem__机制。下面看一下迭代器的例子。

class Next(object):
  def __init__(self, data=1):
    self.data = data
  def __iter__(self):
    return self
  def __next__(self):
    print("__next__ called")
    if self.data > 5:
      raise StopIteration
    else:
      self.data += 1
      return self.data
for i in Next(3):
  print(i)
print("-----------")
n = Next(3)
i = iter(n)
while True:
  try:
    print(next(i))
  except Exception as e:
    break

程序的运行结果如下:

__next__ called
4
__next__ called
5
__next__ called
6
__next__ called
-----------
__next__ called
4
__next__ called
5
__next__ called
6
__next__ called

可见实现了__iter__和__next__方法后,可以通过for in的方式迭代遍历对象,也可以通过iter()和next()方法迭代遍历对象。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Python的条件语句与运算符优先级详解

    Python 条件语句 Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 可以通过下图来简单了解条件语句的执行过程: Python程序语言指定任何非0和非空(null)值为true,0 或者 null为false. Python 编程中 if 语句用于控制程序的执行,基本形式为: if 判断条件: 执行语句-- else: 执行语句-- 其中"判断条件"成立时(非零),则执行后面的语句,而执行内容可以多行,以缩进来区分表示同一范围. el

  • 详解Python中的元组与逻辑运算符

    Python元组 元组是另一个数据类型,类似于List(列表). 元组用"()"标识.内部元素用逗号隔开.但是元素不能二次赋值,相当于只读列表. #!/usr/bin/python # -*- coding: UTF-8 -*- tuple = ( 'abcd', 786 , 2.23, 'john', 70.2 ) tinytuple = (123, 'john') print tuple # 输出完整元组 print tuple[0] # 输出元组的第一个元素 print tupl

  • 浅谈python为什么不需要三目运算符和switch

    对于三目运算符(ternary operator),python可以用conditional expressions来替代 如对于x<5?1:0可以用下面的方式来实现 1if x<5else 0 注: conditional expressions是在python 2.5之前引入的,所以以上代码仅适用于2.5以及之后的版本 对于2.5之前的版本,可以用下面这种形式 X<5and1or 0 对于switch,我们完全可以用dictionary来实现,看下面的例子 >>>d

  • Python入门学习之字符串与比较运算符

    Python字符串 字符串或串(String)是由数字.字母.下划线组成的一串字符. 一般记为 : s="a1a2···an"(n>=0) 它是编程语言中表示文本的数据类型. python的字串列表有2种取值顺序: 从左到右索引默认0开始的,最大范围是字符串长度少1 从右到左索引默认-1开始的,最大范围是字符串开头 如果你的实要取得一段子串的话,可以用到变量[头下标:尾下标],就可以截取相应的字符串,其中下标是从0开始算起,可以是正数或负数,下标可以为空表示取到头或尾. 比如:

  • Python中运算符"=="和"is"的详解

    前言 在讲is和==这两种运算符区别之前,首先要知道Python中对象包含的三个基本要素,分别是:id(身份标识).python type()(数据类型)和value(值).is和==都是对对象进行比较判断作用的,但对对象比较判断的内容并不相同.下面来看看具体区别在哪. Python中比较两个对象是否相等,一共有两种方法,简单来说,它们的区别如下: is是比较两个引用是否指向了同一个对象(引用比较). ==是比较两个对象是否相等. >>> a = [1, 2, 3] >>&g

  • 深入理解Python中的*重复运算符

    在python中有个特殊的符号"*",可以用做数值运算的乘法算子,也是用作对象的重复算子,但在作为重复算子使用时一定要注意 注意的是:*重复出来的各对象具有同一个id,也就是指向在内存中同一块地址,在对各个对象进行操作是一定要注意. 举例来说: >>> alist = [range(3)]*4 >>> alist [[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]] 上面初始化一个二层列表用来模拟矩阵,该矩阵式4X

  • 深入解析Python中的变量和赋值运算符

    Python 变量类型 变量存储在内存中的值.这就意味着在创建变量时会在内存中开辟一个空间. 基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存中. 因此,变量可以指定不同的数据类型,这些变量可以存储整数,小数或字符. 变量赋值 Python中的变量不需要声明,变量的赋值操作既是变量声明和定义的过程. 每个变量在内存中创建,都包括变量的标识,名称和数据这些信息. 每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建. 等号(=)用来给变量赋值. 等号(=)运算符左边是一

  • Python运算符重载详解及实例代码

    Python运算符重载 Python语言提供了运算符重载功能,增强了语言的灵活性,这一点与C++有点类似又有些不同.鉴于它的特殊性,今天就来讨论一下Python运算符重载. Python语言本身提供了很多魔法方法,它的运算符重载就是通过重写这些Python内置魔法方法实现的.这些魔法方法都是以双下划线开头和结尾的,类似于__X__的形式,python通过这种特殊的命名方式来拦截操作符,以实现重载.当Python的内置操作运用于类对象时,Python会去搜索并调用对象中指定的方法完成操作. 类可以

  • Python heapq使用详解及实例代码

     Python heapq 详解 Python有一个内置的模块,heapq标准的封装了最小堆的算法实现.下面看两个不错的应用. 小顶堆(求TopK大) 话说需求是这样的: 定长的序列,求出TopK大的数据. import heapq import random class TopkHeap(object): def __init__(self, k): self.k = k self.data = [] def Push(self, elem): if len(self.data) < self

  • Python 爬虫多线程详解及实例代码

    python是支持多线程的,主要是通过thread和threading这两个模块来实现的.thread模块是比较底层的模块,threading模块是对thread做了一些包装的,可以更加方便的使用. 虽然python的多线程受GIL限制,并不是真正的多线程,但是对于I/O密集型计算还是能明显提高效率,比如说爬虫. 下面用一个实例来验证多线程的效率.代码只涉及页面获取,并没有解析出来. # -*-coding:utf-8 -*- import urllib2, time import thread

  • Python 实现随机数详解及实例代码

    Python3实现随机数 random是用于生成随机数的,我们可以利用它随机生成数字或者选择字符串. random.seed(x)改变随机数生成器的种子seed. 一般不必特别去设定seed,Python会自动选择seed. random.random() 用于生成一个随机浮点数n,0 <= n < 1 random.uniform(a,b) 用于生成一个指定范围内的随机浮点数,生成的随机整数a<=n<=b; random.randint(a,b) 用于生成一个指定范围内的整数,a

  • C++函数重载详解及实例代码

    C++函数的重载 定义 在同一个作用域中,函数名相同,函数的参数列表不同的函数之间构成重载关系,在不同作用域中的同名函数遵循标识符隐藏的原则 ATTENTION:重载与函数的返回值类型无关,因为声明一个函数不需要返回类型,所以无法用来区分哪个函数 常函数和普通成员函数之间构成重载,重载时常对象调用常成员函数,一般对象调用一般成员函数 class A{ - public: void getVal()const{-} void getVal(){-} }; int main(){ const A a

  • Python的运算符重载详解

    一.前言 运算符重载:为运算符定义方法 所谓重载,就是赋予新的含义同一个运算符可以有不同的功能 二.重载作用 让自定义的实例像内建对象一样进行运算符操作让程序简介易读对自定义对象将运算符赋予新的规则 运算符和特殊方法 运算符重载 # @function:运算符重载 # @Description: 一只萤火虫 class MyInteger: """ 创建一个自定义的整数类型 """ def __init__(self, data=0): # 1.

  • Python入门教程之运算符重载详解

    目录 如何重载Python中的运算符 在 Python中重载比较运算符 重载相等和小于运算符 用于运算符重载的 Python 魔术方法或特殊函数 二元运算符 比较运算符 赋值运算符 一元运算符 运算符重载意味着赋予超出其预定义的操作含义的扩展含义.例如运算符 + 用于添加两个整数以及连接两个字符串和合并两个列表.这是可以实现的,因为 '+' 运算符被 int 类和 str 类重载.您可能已经注意到,相同的内置运算符或函数对不同类的对象显示不同的行为,这称为运算符重载. # Python 程序显示

  • Python 字典的使用详解及实例代码

    目录 字典长什么样 字典内能放什么 访问字典内容 修改字典内容 删除字典数据 字典内置函数 字典是Python实现散列表数据结构的形式,表现映射的关系,一对一. 字典长什么样 {}这是一个空字典,可以看出字典是由两个花括号组成的. 在看这个{'a':1},这里面装了一对数据,'a'可称为键,1称为值 这个{'键1':'值1', '键2':'值2'}每一对数据 字典内能放什么 字典内的健是唯一的,在字典内所有内容中只存在一个,但值可以重复出现. 健只能是不变的值,比如字符串,数字,元组 值可以随意

  • Python 操作MySQL详解及实例

    Python 操作MySQL详解及实例 使用Python进行MySQL的库主要有三个,Python-MySQL(更熟悉的名字可能是MySQLdb),PyMySQL和SQLAlchemy. Python-MySQL资格最老,核心由C语言打造,接口精炼,性能最棒,缺点是环境依赖较多,安装复杂,近两年已停止更新,只支持Python2,不支持Python3. PyMySQL为替代Python-MySQL而生,纯python打造,接口与Python-MySQL兼容,安装方便,支持Python3. SQLA

  • C++中的运算符重载详解

    目录 1.引例 2.类中自动建立的函数 3.重载赋值运算符解析 总结 1.引例 class Complex { private: double Real,Image; public: Complex():Real(0),Image(0) {} Complex(double r, double i) : Real(r),Image(i) {} ~Complex() {} }; int main() { Complex c1(1.2,2.3); Complex c2(45,56); Complex

随机推荐