您的位置:首页 > 编程语言 > Python开发

Python 魔法方法简介

2017-08-06 12:09 417 查看

1、什么是魔法方法?

  魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一切都是自动触发的。它们经常是两个下划线包围来命名的(比如 __init__,__lt__),Python的魔法方法是非常强大的,所以了解其使用方法也变得尤为重要!

2、__init__(self[, ...]),__new__(cls[, ...]),__del__(self)

  __init__ 构造器,当一个实例被创建的时候初始化的方法。但是它并不是实例化调用的第一个方法,__new__才是实例化对象调用的第一个方法,它只取下 cls参数,并把其他参数传给 __init__。 __new__很少使用,但是也有它适合的场景,尤其是当类继承自一个像元组或者字符串这样不经常改变的类型的时候。

  __new__ 使用时注意以下四点:

1) __new__  是在一个对象实例化的时候所调用的第一个方法; 2)它的第一个参数是这个类,其他的参数是用来直接传递给 __init__ 方法; 3) __new__  返回一个构建的实例; 4) __new__  决定是否要使用该 __init__ 方法,因为 __new__ 可以调用其他类的构造方法或者直接返回别的实例对象来作为本类的实例,如果 __new__ 没有返回实例对象,则__init__ 不会被调用; 5) __new__  主要是用于继承一个不可变的类型比如一个 tuple 或者 string。       __new__实现单例模式:
1 class Person(object):
2     def __init__(self, name, age):
3         self.name = name
4         self.age = age
5
6     def __new__(cls, *args, **kwargs):
7         if not hasattr(cls,'instance'):
8             cls.instance = super(Person,cls).__new__(cls)
9         return cls.instance
10
11
12 a = Person('p1',20)
13 b = Person('p2',21)
14 print(a == b)
15 #这里的打印结果是True,可见a,和b都是同一个实例
16 #单例作用:
17   #第一、控制资源的使用,通过线程同步来控制资源的并发访问;
18   #第二、控制实例产生的数量,达到节约资源的目的;
19   #第三、作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不##相关的两个线程或者进程之间实现通信。比如,数据库连接池的设计一般采用单例模式,数据库连接是一种数据库资源。

  

  __del__ 析构器,当实例被销毁时调用。

 

3、__call__(self[,args ...]),__getitem__(self,key),__setitem__(self,key,value)

  __call__ 允许一个类的实例像函数一样被调用,如下。

1 class Person(object):
2     def __init__(self, name, age):
3         self.name = name
4         self.age = age
5         self.instance = add
6
7     def __call__(self,*args):
8         return self.instance(*args)
9
10 def add(args):
11     return args[0] + args[1]
12
13 a = Person('p1', 20)
14 print(a([1,2]))
15 #这里将打印 3
16 #可见当创建a这个对象之后,如果定义了__call__函数则对象是可以像函数一样调用的。

  

  __getitem__ 定义获取容器中指定元素的行为,相当于self[key],如下。

1 class Person(object):
2     def __init__(self, name, age):
3         self.name = name
4         self.age = age
5         self._registry = {
6             'name': name,
7             'age': age
8         }
9
10     def __call__(self, *args):
11         return self.instance(*args)
12
13     def __getitem__(self, key):
14         if key not in self._registry.keys():
15             raise Exception('Please registry the key:%s first !' % (key,))
16         return self._registry[key]
17
18 a = Person('p1', 20)
19 print(a['name'],a['age'])
20 #这里打印的是 'p1' 20
21 #可见__getitem__使实例可以像字典一样访问

  

  __setitem__ 设置容器中指定元素的行为,相当于self[key] = value 。

 

4、__getattr__(self,name),__getattribute__(self,name),__setattr__(self,name,value),__delattr__(self,name)

  __getattr__ ():当用户试图访问一个不存在属性时触发;

  __getattribute__(): 当一个属性(无论存在与否)被访问时触发;

  __setattr__ ():当一个属性被设置时触发;

  __delattr__ ():当一个属性被删除时触发。

1 class Person(object):
2     def __init__(self, name, age):
3         self.name = name
4         self.age = age
5         self._registry = {
6             'name': name,
7             'age': age
8         }
9
10     def __getattribute__(self, item):
11         #注意此处不要再访问属性,如self.__dict__[item]
12         #因为self.__dict__依然会被__getattribute__拦截,这样就会陷入死循环
13         return object.__getattribute__(self,item)
14
15     def __getattr__(self, item):
16         print("don't have the attribute ",item)
17         return False
18
19     def __setattr__(self, key, value):
20         self.__dict__[key] = value
21
22
23 a = Person('p1', 20)
24 print(a.cs)          #这里会打印 don't have the attribute cs 以及 False
25 a.cs = '测试'         #这里设置该属性值为'测试'
26 print(a.cs)           #这里将打印出'测试'

   

  至此,转载请注明出处。

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: