python类中的__call__、__init__、__getattr__、__setattr__、__setattr__详解

时间:2021-08-18 21:57:35
__new__(cls, *args, **kwargs)
创建对象时调用,返回当前对象的一个实例(注意:这里的第一个参数是cls即class本身)

__init__(self, *args, **kwargs)
创建完对象后调用,对当前对象的实例的一些初始化,无返回值

__call__(self, *args, **kwargs)
如果类实现了这个方法,相当于把这个类型的对象当作函数来使用,相当于 重载了括号运算符

class O(object):

    
def __init__(self, *args, **kwargs):
        
print "init"
        
super(O, self).__init__(*args, **kwargs)

    
def __new__(cls, *args, **kwargs):
        
print "new", cls
        
return super(O, cls).__new__(cls, *args, **kwargs)

    
def __call__(self,  *args, **kwargs):
        
print "call"

test = O('12')  # output new <class '__main__.O'> , init
test()  # output call



__str__
对象打印出来的字符串(返回用户看到的)
__repr
对象打印出来的字符串(返回开发者看到的
class Student(object):
def __init__(self, name):
self.name = name

def __str__(self):
print '__str__'
return 'name of this student is %s'%self.name

def __repr__(self):
return 'name of this student is %s'%self.name

print Student('Xiaoming') # output: __str__, name of this student is Xiaoming
>>> print Student('Xiaoming') # output: __repr__, name of this student is Xiaoming



__iter__
可以使类的实例是一个可迭代的对象,需实现next()方法
ex:
class Fib(object):

def __init__(self):
self.a, self.b = 0, 1 # 初始化两个计数器ab

def __iter__(self):
return self # 实例本身就是迭代对象,故返回自己

def next(self):
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 100000: # 退出循环的条件
raise StopIteration();
return self.a # 返回下一个值

>>> for n in Fib():
... print n
...
1
1
2
3
5
...
46368
75025


__getitem__

对象像list那样按照下标取出元素(注意:如若需要使用切片等方法需要自己实现)

class Fib(object):
def __getitem__(self, n):
a, b = 1, 1
for x in range(n):
a, b = b, a + b
return a

f = Fib()
print f[0] # output: 1
print f[1] # output: 1
print f[10] # output: 89


__getattr__(self, name)
当调用不存在的属性时访问这个方法

__get__(self, name)
无条件被调用,通过实例访问属性。如果class中定义了__getattr__(),则__getattr__()不会被调用(除非显示调用或引发AttributeError异常) 

__getattribute__((self, instance, owner)
如果class定义了它,则这个class就可以称为descriptor。owner是所有者的类,instance是访问descriptor的实 例,如果不是通过实例访问,而是通过类访问的话,instance则为None。(descriptor的实例自己访问自己是不会触发__get__,而 会触发__call__,只有descriptor作为其它类的属性才有意义。)(所以下文的d是作为C2的一个属性被调用) 

class C(object):
    a1 = 'abc'
   
def
__getattribute__(self, *args, **kwargs):
       
print("__getattribute__() is called")
       
return object.__getattribute__(self, *args, **kwargs)

   
def __getattr__(self, name):
       
print("__getattr__() is called ")
       
return name + " from getattr"

   
def
__get__(self, instance, owner):
        
print("__get__() is called", instance, owner)
       
return self

   
def foo(self, x):
       
print(x)

class C2(object):
    d = C()

if __name__ == '__main__':
    c = C()
    c2 = C2()
   
print(c.a1)
   
# __getattribute__() is called,
    # abc
   
print(c.a2)
   
# __getattribute__() is called
    # __getattr__() is called
    # a2 from getattr
   
print(c2.d.a1)
   
# ('__get__() is called', <__main__.C2 object at 0x00000000027444A8>, <class '__main__.C2'>)
    # __getattribute__() is called
    # abc

 


__setattr__(self, name)
设置属性的方法

class A(object):
   
def __setattr__(self, *args, **kwargs):
       
print 'call func set attr'
       
return
object.__setattr__(self, *args, **kwargs)
a = A()
a.a1 =
123
print a.a1