wordpress 双语站点,大丰有做网站的,欧美做视频网站有哪些,网页设计叫什么岗位1#xff1a;运算符重载介绍运算符重载#xff0c;就是在某个类的方法中#xff0c;拦截其内置的操作(比如#xff1a;#xff0c;-#xff0c;*#xff0c;/,比较#xff0c;属性访问#xff0c;等等)#xff0c;使其实例的行为接近内置类型。当类的实例出现在内置操…1运算符重载介绍运算符重载就是在某个类的方法中拦截其内置的操作(比如-*/,比较属性访问等等)使其实例的行为接近内置类型。当类的实例出现在内置操作中时(比如两个实例相加 ),Python会自动调用你的方法(比如你重载的__add__方法)并且你的方法的返回值会作为相应操作的结果。Python3中的运算符重载运算符重载让类拦截常规的Python操作。类可以重载所有Python表达式运算符。类也可以重载打印函数调用属性访问等内置运算。重载是通过在一个类中提供特殊名称的方法来实现的。2Python3中常见运算符重载方法3运算符重载方法示例3.1索引和分片:__getitem__和__setitem__在实例进行 类似 X[2] 这种操作时会调用__getitem__方法在实例进行 类似 X[2] value 这种操作时会调用__setitem__方法索引:# encodinggbk class Test: def __getitem__(self, item): print(item:,item) return item**3 # 返回 x 的三次方 def __setitem__(self, key, value): print(key,value) t Test()print(t[2]) # 会调用__getitem__函数 返回2 的三次方print(t[3]) # 会调用__getitem__函数 返回3 的三次方 t[3] 100 # 会调用__setitem__分片# encodinggbk class Test: def __getitem__(self, item): print(item:,item) if isinstance(item,int): return item**3 # 返回 x 的三次方 else: print(slicing,item.start,item.stop,item.step) return [x**3 for x in range(item.start,item.stop,item.step)] def __setitem__(self, key, value): print(key,value) # do something t Test()# 索引print(t[2]) # 会调用__getitem__函数 返回2 的三次方print(t[3]) # 会调用__getitem__函数 返回3 的三次方t[3] 100 # 会调用__setitem__ print(**60)# 分片print(t[2:10:2]) # 传入的是分片对象t[2:5] 1003.2返回数值:__index__ (__index__不是索引)在需要整型数字的上下文中会调用__index__函数__index__会为实例返回一个整数值。比如调用函数hex(X),bin(X)时会去调用X的__index__方法# encodinggbk class Test: def __index__(self): return 100 X Test()print(hex(X))print(bin(X))print(oct(X))3.3可迭代对象__iter__,__next__如果要使自己定义的类的对象是可迭代的那么就必须使这个类支持迭代协议即重载__iter__,__next__方法。迭代协议(包括两种对象) 可迭代对象(Iterable)里面包含了__iter__() 可迭代对象X, 通过调用 I iter(X) 可返回一个迭代器对象再调用next(I) 就可以迭代X中的元素。 迭代器对象(Iterator)里面包含了__iter__() 和 __next__()迭代过程(for循环等迭代中默认的操作) 首先调用 iter函数 I iter(X); 调用的是X.__iter__() 然后对返回对象I调用nextnext(I); 调用的是 I.__next__()直到迭代完成。3.3.1:单遍迭代即只能迭代一次# encodinggbk class Fibonacci: def __init__(self, n): self.a 0 self.b 1 self.max_cnt n def __iter__(self): return self def __next__(self): self.a, self.b self.b, self.a self.b if self.a self.max_cnt: raise StopIteration return self.a fib Fibonacci(5)print(fib) print(1:* * 30)I iter(fib) # 调用 fib.__iter__()(返回的是self及fib)print(next(I)) # 调用的是 fib.__next__()fib对象中的a,b属性值会改变。print(next(I)) # 调用的是 fib.__next__() print(1:* * 30) # for循环首先调用的是I iter(fib)此处返回的是self即fib再调用next(I)即fib.__next__(),此时其值已经取完2个了因此从第3个开始取。for x in fib: print(x)print(2:* * 30)# 此处与上面的循环一样但是fib.__next__()已经把数据取完了故这里不会有输出for x in fib: print(x) print(3:* * 30) #i iter(fib) # 返回self即fibfor ii in i: # 与上面的 for x in fib 一样不会再输出! print(ii)3.3.2:多遍迭代即可以多次迭代使用# encodinggbk class Fibonacci: def __init__(self, n): self.a 0 self.b 1 self.max_cnt n def __iter__(self): return FibonacciIter(self.a,self.b,self.max_cnt) class FibonacciIter: def __init__(self,a,b,max_cnt): self.a a self.b b self.max_cnt max_cnt def __next__(self): self.a, self.b self.b, self.a self.b if self.a self.max_cnt: raise StopIteration return self.a fib Fibonacci(5) I iter(fib)print(next(I)) # 调用的是FibonacciIter对象中的__next__方法fib对象中的a,b属性没有任何变化。print(next(I))print(next(I))print(next(I))print(next(I)) # 迭代完了# print(next(I)) # 上一步迭代完了再次调用next(I)会抛出异常 print(1:* * 30) print(fib)print(1:* * 30)# for循环(默认调用)首先调用一次 I iter(fib) 即fib.__iter__(),返回一个重新创建FibonacciIter对象 # 然后再调用 next(I),即I.__next__() (也就是FibonacciIter类中的__next__()函数)直到迭代完。for x in fib: print(x)print(2:* * 30)# 与上面for循环调用过程一样。for x in fib: print(x) print(3:* * 30) # i iter(fib)# for ii in i: # 这里会报错因为iter(fib)返回FibonacciIter的实例 i # 而for循环首先会调用 iter(i) 即 调用FibonacciIter中的__iter__函数而FibonacciIter类中没有重载此函数# print(ii)3.3.3:__iter__ 加 yield 实现多遍迭代# encodinggbk class Test: def __init__(self,start,stop): self.start start self.stop stop def __iter__(self): print(self.start,self.stop1) for value in range(self.start,self.stop1): yield value**2 t Test(1,3)# 说明for循环中首先调用 I iter(t),即调用的是t.__iter__(),在__iter__函数中有yield语句# yield语句会自动创建一个包含 __next__ 方法的类并返回它的实例# 然后会调用 next(I),I 为yield自动创建类的实例for i in t: print(i)print(**40)for i in t: print(i)3.4属性访问__getattr__,__getattribute__和__setattr__3.4.1 __getattr__,__getattribute____getattr__ 会拦截未定义的属性即在使用点号访问属性时(如X.属性) 如果Python通过其继承树搜索过程中没有找到这个属性那么就会自动调用__getattr__方法。__getattribute__ 会拦截所有属性。# encodinggbk class Test: aa 0 def __init__(self): self.age 100 def __getattr__(self, item): print(in __getattr__:,item) t Test()print(1: ,t.__dict__)# 属性引用属性找不到时就会调用__getattr__方法print(t.aa) # 在类中存在类属性 aaprint(2: * * 30) print(t.bb) # t.__dict__ 中不存在属性 bb其父类中也没有属性bb故会调用__getattr__方法print(3: * * 30)print(t.age) # 存在实例属性age不会调用__getattr__方法t.age 200print(4: ,t.__dict__) 1: {age: 100}02:******************************in __getattr__: bbNone3:******************************1004: {age: 200}3.4.2__setattr____setattr__会拦截所有的属性赋值如果定义或者继承了__setattr__方法那么 self.attr value,将会变成 self.__setattr__(attr,value)这里要注意的是 如果在__setattr__方法中有使用 self.attr value 的赋值形式那么__setattr__将会进入死循环因为self.attr value 的赋值形式会调用self.__setattr__(attr,value)而__setattr__方法中又使用self.attr value进行赋值从而进入一个循环。# encodinggbk class Test: def __init__(self): # 构造函数中对 self.age 进行赋值如果继承了__setattr__方法 # 就会把self.age 100 变成 self.__setattr__(age,100) self.age 100 def __getattr__(self, item): print(in __getattr__:,item) def __setattr__(self, key, value): print(in __setattr__:,key,value) # self.aa 100 # 这样赋值会导致死循环因为 self.aa 100 会变成 self.__setattr__(aa,100)而后者又调用了前者 if key ! age: # 拦截 age属性 self.__dict__[key] value t Test()print(1: **30)print(t.__dict__) # 此处输出为{}虽然在构造函数中有self.age 100赋值但是在 __setattr__方法中把它过滤掉啦print(2: **30)print(t.age) # 由于 age属性被拦截掉了故访问t.age会调用 __getattr__方法print(3: **30)t.age 200 # 会把 age给拦截掉t.name ixusy # 不存在name属性因此会调用__setattr__在__setattr__方法中把 name属性 添加到属性字典__dict__中 # 后面就可以通过使用t.name进行访问。print(4: **30)print(t.__dict__)print(5: **30) 输出结果in __setattr__: age 1001:******************************{}2:******************************in __getattr__: ageNone3:******************************in __setattr__: age 200in __setattr__: name ixusy4:******************************{name: ixusy}5:******************************3.4.3 __getattr__ 和 __setattr__总结__getattr__ :拦截不存在的属性引用__setattr__拦截所有的属性赋值当心死循环3.5调用表达式__call__在实例上执行函数调用表达式就会自动调用__call__函数# encodinggbk class Test: def __call__(self, *args, **kwargs): print(call:,args,kwargs) t Test()t(1,2,3)t(1,2,3,b22)# 传递参数需要符合函数传递参数的规则# t(1,a2,3,b22) # 这样传递会报错3.6字符串显示__str__ 和 __repr____str__ 和 __repr__ 都是用于显示字符串只不过是他们的使用场景不同而已。__str__ 打印操作(print)内置函数str调用,会优先调用__str__ 如果没有重载__str__就会去调用__repr____repr__用于所有其他场景包括交互式命令行repr函数嵌套显示以及没有可用__str__时print和str的调用。__repr__ 可用于任何地方__str__用于print 和 str函数。3.7比较运算# encodinggbk class Person: def __init__(self,name,age,height): self.name name self.age age self.height height # 比较规则可以自行定义 # 下面规则为 # 1年龄小的 比较结果为小 # 2年龄相等的比较身高身高小结果为小 # 3其他情况返回False def __lt__(self, other): if self.age other.age: return True elif self.age other.age: return self.height other.height else: return False 还可以重载 __gt__ __le__ __ge__ __eq__ __ne__ 需要注意的是 p1 p2,并不表示p1 ! p2, 具体要看你怎么实现 __eq____ne__方法 实际中尽可能使得__eq____ne__方法的实现符合正常的逻辑。 p1 Person(ixusy88,18,188)p2 Person(i,18,180)print(p1 p2) # False p1 Person(ixusy88,18,177)p2 Person(i,18,180)print(p1 p2) # True