__slots__:定义类时,使用__slots__变量可以限制能添加的实例的属性
形如:__slots__ = ['name','age']
这样实例化的对象只能绑定到name和age属性,其他属性则无法被绑定
1
2
3
4
5
6
7
8
9
|
class People:
__slots__ = [ 'name' , 'age' ]
def __init__( self ,name,age):
self .name = name
self .age = age
p = People( 'laowang' , 18 )
print (p.name)
p.sex = 'male'
print (p.sex)
|
执行结果:
1
2
3
4
5
6
7
8
9
|
laowang Traceback (most recent call last): File "C:/" , line 43 , in <module>
p.sex = 'male'
AttributeError: 'People' object has no attribute 'sex'
|
可以看出name属性初始化成功并且可以访问,但是sex属性无法添加
__call__方法:只要定义类型的时候,实现__call__函数,这个类型就成为可调用的
1
2
3
4
5
6
7
8
9
10
11
|
class People:
def __init__( self ,name):
self .name = name
#
def __call__( self , * args, * * kwargs):
print ( 'call' )
#
p = People( 'egon' )
print ( callable (People))
print ( callable (p))
p() |
执行结果为:
True
True
call
意味着People及其产生的对象均为可调用的,并且:对象()会执行__call__方法
__getitem__、__setitem__、__delitem__方法:提供以字典的方式操作对象属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class Foo:
def __init__( self ,name):
self .name = name
def __getitem__( self , item):
# print('getitem',item)
return self .__dict__[item]
def __setitem__( self , key, value):
print ( 'setitem-----<' )
self .__dict__[key] = value
def __delitem__( self , key):
self .__dict__.pop(key)
# self.__dict__.pop(key)
# def __delattr__(self, item):
# print('del obj.key时,我执行')
# self.__dict__.pop(item)
f = Foo( 'egon' )
f[ 'name' ] = 'egon'
print (f.name)
f[ 'age' ] = 18
print (f.__dict__)
del f[ 'age' ]
|
__iter__、__next__方法:可以实现一个迭代器协议,类定义中加入这两个方法可以将类实例化的对象变为可迭代的对象
需要注意下的就是__next__中必须控制iterator的结束条件,不然就死循环了
下例利用此原理实现了一个简单的range()函数的功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Range :
def __init__( self ,start,stop):
self .start = start
self .stop = stop
pass
def __iter__( self ):
return self
def __next__( self ):
if self .start > = self .stop:
raise StopIteration
n = self .start
self .start + = 1
return n
for i in Range ( 1 , 10 ):
print (i)
|
__del__方法:析构函数,当对象在内存中被释放时,自动触发执行
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Open :
def __init__( self ,filepath,mode = 'r' ,encode = 'utf-8' ):
self .f = open (filepath,mode = mode,encoding = encode)
def write( self ):
pass
def __getattr__( self , item):
return getattr ( self .f,item)
def __del__( self ):
print ( '----->del' )
self .f.close()
f = Open ( 'a.txt' , 'w' )
f1 = f
del f
print ( '=========>' )
|
__enter__、__exit__方法:实现上下文管理协议,即with语句,这个跟文件操作时使用with语句一样:
1
2
|
with open ( 'filepath/filename' , 'r' ,encoding = 'utf-8' ) as f:
'代码块'
|
在类定义时定义__enter__、__exit__方法可以让类产生的对象使用with语句
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Foo:
def __enter__( self ):
print ( '=====》enter' )
return self
def __exit__( self , exc_type, exc_val, exc_tb):
print ( 'exit' )
print ( 'exc_type' ,exc_type)
print ( 'exc_val' ,exc_val)
print ( 'exc_tb' ,exc_tb)
return True
with Foo() as obj: #res=Foo().__enter__() #obj=res
print ( 'with foo的自代码块' ,obj)
raise NameError( '名字没有定义' )
print ( '************************************' )
print ( '------>' )
|
__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行,但是__exit__如果有返回值,则with语句块之外的代码可以正常执行
__str__方法:当类的方法被调用时,会调用此方法返回一个字符串(为了好看与打印相关重要信息)
元类:
关于元类的详细讲解可参阅此文:深刻理解Python中的元类(metaclass)
本文转自 AltBoy 51CTO博客,原文链接:http://blog.51cto.com/altboy/1919295