__setattr__()、__getattr__()、__delattr__()
第一次接触这几个方法时,是使用pymongo的时候。pymongo经常会使用['']或"."来获取数据库或集合对象。
__xxxattr__:使用 '.' 的方式操作属性时被调用
__setattr__:每当属性被赋值的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环
__getattr__:当访问不存在的属性时会调用该方法
__delattr__:当删除属性时调用该方法
class A(object):
def __init__(self):
self.A = "aa"
self.C = "CC"
del self.C
def __setattr__(self,name,value):
'''
@summary: 每当属性被赋值的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环
'''
print "__setattr__:Set %s Value %s"%(name,value)
self.__dict__[name] = value
def __getattr__(self,name):
'''
@summary: 当访问不存在的属性时会调用该方法
'''
print "__getattr__:No attribute named '%s'"%name
return None
def __delattr__(self,name):
'''
@summary: 当删除属性时调用该方法
'''
print "__delattr__:Delect attribute '%s'"%name
del self.__dict__[name]
print self.__dict__
if __name__ == "__main__":
X = A()
a = X.aa
输出为:
__setattr__:Set A Value aa
__setattr__:Set C Value CC
__delattr__:Delect attribute 'C'
{'A': 'aa'}
__getattr__:No attribute named 'aa'
Python __setitem__()、__getitem__()、__delitem__()
__xxxitem__:使用 [''] 的方式操作属性时被调用
__setitem__:每当属性被赋值的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环
__getitem__:当访问不存在的属性时会调用该方法
__delitem__:当删除属性时调用该方法
class A(object):
def __init__(self):
self['B'] = "BB"
self['D'] = "DD"
del self['D']
def __setitem__(self,name,value):
'''
@summary: 每当属性被赋值的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环
'''
print "__setitem__:Set %s Value %s"%(name,value)
self.__dict__[name] = value
def __getitem__(self,name):
'''
@summary: 当访问不存在的属性时会调用该方法
'''
print "__getitem__:No attribute named '%s'"%name
return None
def __delitem__(self,name):
'''
@summary: 当删除属性时调用该方法
'''
print "__delitem__:Delect attribute '%s'"%name
del self.__dict__[name]
print self.__dict__
if __name__ == "__main__":
X = A()
b = X['bb']
输出:
__setitem__:Set B Value BB
__setitem__:Set D Value DD
__delitem__:Delect attribute 'D'
{'B': 'BB'}
__getitem__:No attribute named 'bb'
Python __len__()、__reversed__()、__contains__()
__len__():当使用len(A)该对象时调用该方法,当没有该方法是会报错,且返回数据不为整数也会报错
class A(object):
def __init__(self,num):
self.num = num
self.start_num = -1
def __len__(self):
'''
@summary: 当使用len(Test)该对象时调用该方法,当没有该方法是会报错,且返回数据不为整数也会报错
'''
print "__len__"
return self.num - self.start_num - 1
if __name__ == "__main__":
print len(A(10))
输出:
__len__ 10
__reversed__():当使用reversed函数翻转对象时调用
class A(object):
def __init__(self,num):
self.num = num
def __reversed__(self):
'''
@summary: 当使用reversed函数翻转对象时调用
'''
ret = []
for i in range(self.num):
ret.append(self.num - i-1)
return ret
if __name__ == "__main__":
print reversed(A(10))
输出:
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
__contains__():当使用in,not in 对象的时候 调用(not in 是在in完成后再取反,实际上还是in操作)
class A(object):
def __init__(self,num):
self.num = num
def __contains__(self, item):
'''
@summary:当使用in,not in 对象的时候 ,not in 是在in完成后再取反,实际上还是in操作
'''
print "__contains__:%s is in?"%item
if item < self.num and item >= 0:
return True
return False
if __name__ == "__main__":
if 3 in A(10):print "True"
else:print False
if 3 not in A(10):print "True"
else:print False
输出:
__contains__:3 is in? True __contains__:3 is in? False
__iter__():迭代器,生成迭代对象时调用,返回值必须是对象自己,然后for可以循环调用next方法
next():每一次for循环都调用该方法(必须存在)
class A(object):
def __init__(self,num):
self.num = num
self.start_num = -1
def __iter__(self):
'''
@summary: 迭代器,生成迭代对象时调用,返回值必须是对象自己,然后for可以循环调用next方法
'''
print "__iter__"
return self
def next(self):
'''
@summary: 每一次for循环都调用该方法(必须存在)
'''
self.start_num += 1
if self.start_num >= self.num:
raise StopIteration()
return self.start_num
if __name__ == "__main__":
for i in A(10):print i,
输出:
__iter__ 0 1 2 3 4 5 6 7 8 9
python 中__getitem__ 和 __iter__ 的区别
# -*- coding: utf-8 -*-
class Library(object):
def __init__(self):
self.books = { 'title' : 'a', 'title2' : 'b', 'title3' : 'c', }
def __getitem__(self, i):
return self.books[i]
def __iter__(self):
# 方法1 使用生成器
for titles in self.books:
yield self.books[titles]
# 方法2 使用迭代器
# return self.books.itervalues()
library = Library()
# 1.普通方法
print library.books['title']
# 2.使用__getitem__
print library['title']
# 3.迭代器
for book in library:
print book
问题:那__getitem__可以替代__iter__方法吗?
1、list
# -*- coding: utf-8 -*-
class Library(object):
def __init__(self):
self.books = [ 'title' , 'a', 'title2' , 'b', 'title3' , 'c', ]
def __getitem__(self, i):
return self.books[i]
# def __iter__(self):
# 方法1 使用生成器
# for titles in self.books:
# yield self.books[titles]
# 方法2 使用迭代器
# return self.books.itervalues()
library = Library()
# 1.普通方法
print(library.books[1])
# 2.使用__getitem__
print(library[1])
# 3.迭代器
for book in library:
print(book)
结果为:
a a title a title2 b title3 c
2、dict
# -*- coding: utf-8 -*-
class Library(object):
def __init__(self):
self.books = { 'title' : 'a', 'title2' : 'b', 'title3' : 'c', }
def __getitem__(self, i):
return self.books[i]
# def __iter__(self):
# 方法1 使用生成器
# for titles in self.books:
# yield self.books[titles]
# 方法2 使用迭代器
# return self.books.itervalues()
library = Library()
# 1.普通方法
print(library.books[1])
# 2.使用__getitem__
print(library[1])
# 3.迭代器
for book in library:
print(book)
结果为:
Traceback (most recent call last):
File "C:/Users/CUI/Desktop/1.py", line 20, in <module>
print(library.books[1])
KeyError: 1
结论:当字段为索引行数据类型(如:list, tuple,str)时,可以替换,当字段为hash型类型(如dict,set)时,不能替换。
Python __call__()
__call__() :__call__() 方法可以让类像方法一样被调用
class Call(object):
def __init__(self):
pass
def __call__(self,ret):
'''
@summary: 将类对象当做方法直接使用时,调用该方法
'''
print "__call__:Negate ",ret
ret = - ret
return ret
if __name__ == "__main__":
A = Call()
print A(15)
输出为:
__call__:Negate 15 -15
Python __enter__()、__exit__()
__enter__():在使用with语句时调用,会话管理器在代码块开始前调用,返回值与as后的参数绑定
__exit__():会话管理器在代码块执行完成好后调用,在with语句完成时,对象销毁之前调用
test.txt:
Hello world!
class Test(object):
def __init__(self,name,flag):
self.filename = name
self.flag = flag
def __enter__(self):
'''
@summary: 使用with语句是调用,会话管理器在代码块开始前调用,返回值与as后的参数绑定
'''
print "__enter__:Open %s"%self.filename
self.f = open(self.filename,self.flag)
return self.f
def __exit__(self,Type, value, traceback):
'''
@summary: 会话管理器在代码块执行完成好后调用(不同于__del__)(必须是4个参数)
'''
print "__exit__:Close %s"%self.filename
self.f.close()
def __del__(self):
print "__del__"
if __name__ == "__main__":
with Test('test.txt','r+') as f:
content = f.read()
print content
print "end"
输出:
__enter__:Open test.txt Hello world! __exit__:Close test.txt del end
综合:
1、
__setattr__、__getattr__、__delattr__、__setitem__、__getitem__、__delitem__
#coding=utf-8
'''
Created on 2015-8-27
@author: xhw
@explain: 属性相关
'''
'''使用super可以调用父类的方法,或重写前的内置方法'''
class Test(object):
def __init__(self):
self.A = "aa"
self['B'] = "BB"
self.C = "CC"
self['D'] = "DD"
del self.C
del self['D']
"------------------------------------------------------------------------------"
"----------------------attr:使用 '.' 的方式操作属性时被调用-----------------------"
"------------------------------------------------------------------------------"
def __setattr__(self,name,value):
'''
@summary: 每当属性被赋值的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环
'''
print "__setattr__:Set %s Value %s"%(name,value)
self.__dict__[name] = value
def __getattr__(self,name):
'''
@summary: 当访问不存在的属性时会调用该方法
'''
print "__getattr__:No attribute named '%s'"%name
return None
def __delattr__(self,name):
'''
@summary: 当删除属性时调用该方法
'''
print "__delattr__:Delect attribute '%s'"%name
del self.__dict__[name]
print self.__dict__
"------------------------------------------------------------------------------"
"--------------------item:使用 [''] 的方式操作属性时被调用-------------------------"
"------------------------------------------------------------------------------"
def __setitem__(self,name,value):
'''
@summary: 每当属性被赋值的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环
'''
print "__setitem__:Set %s Value %s"%(name,value)
self.__dict__[name] = value
def __getitem__(self,name):
'''
@summary: 当访问不存在的属性时会调用该方法
'''
print "__getitem__:No attribute named '%s'"%name
return None
def __delitem__(self,name):
'''
@summary: 当删除属性时调用该方法
'''
print "__delitem__:Delect attribute '%s'"%name
del self.__dict__[name]
print self.__dict__
if __name__ == "__main__":
A = Test()
a = A.aa
b = A['bb']
2、__len__、__iter__、__reversed__、__contains__、__concat__
#coding=utf-8
'''
Created on 2015-8-27
@author: xhw
@explain: pass
'''
class Test(object):
def __init__(self,num):
self.num = num
self.start_num = -1
def __len__(self):
'''
@summary: 当使用len(Test)该对象时调用该方法,当没有该方法是会报错,且返回数据不为整数也会报错
'''
print "__len__"
return self.num - self.start_num - 1
def __iter__(self):
'''
@summary: 迭代器,生成迭代对象时调用,返回值必须是对象自己,然后for可以循环调用next方法
'''
print "__iter__"
return self
def next(self):
'''
@summary: for循环时调用该方法
'''
self.start_num += 1
if self.start_num >= self.num:
raise StopIteration()
return self.start_num
def __reversed__(self):
'''
@summary: 当使用reversed函数翻转对象时调用
'''
ret = []
for i in range(self.num - 1):
ret.append(self.num - i)
return ret
def __contains__(self, item):
'''
@summary:当使用in,not in 对象的时候 ,not in 是在in完成后再取反,实际上还是in操作
'''
print "__contains__:%s is in?"%item
if item < self.num and item >= 0:
return True
return False
def __concat__(self,other):
'''
@summary: 据说是在使用‘+’操作符操作对象时调用,但不知道该怎么调用(貌似string 和 list内置该方法)
'''
print "__concat__:Concat ",other
ret = []
for i in range(self.num - 1):
ret.append(self.num - i)
return ret.extend(other)
if __name__ == "__main__":
print len(Test(10))
for i in Test(10):print i
print reversed(Test(10))
if 3 in Test(10):print "True"
else:print False
if 3 not in Test(10):print "True"
else:print False
3、 __call__、with、__enter__、__exit__
#coding=utf-8
'''
Created on 2015-8-28
@author: xhw
@explain: pass
'''
class Call(object):
def __init__(self):
pass
def __call__(self,ret):
'''
@summary: 将类对象当做方法直接使用时,调用该方法
'''
print "__call__:Negate ",ret
ret = - ret
class Test(object):
def __init__(self,name,flag):
self.filename = name
self.flag = flag
def __enter__(self):
'''
@summary: 使用with语句是调用,会话管理器在代码块开始前调用,返回值与as后的参数绑定
'''
print "__enter__:Open %s"%self.filename
self.f = open(self.filename,self.flag)
return self.f
def __exit__(self,Type, value, traceback):
'''
@summary: 会话管理器在代码块执行完成好后调用(不同于__del__)(必须是4个参数)
'''
print "__exit__:Close %s"%self.filename
self.f.close()
if __name__ == "__main__":
A = Call()
print A(15)
with Test('test.txt','r+') as f:
content = f.read()
print content