知行编程网知行编程网  2022-10-18 00:00 知行编程网 隐藏边栏  8 
文章评分 0 次,平均分 0.0
导语: 本文主要介绍了关于python魔法方法有什么用的相关知识,包括python魔法变量,以及什么是python的类这些编程知识,希望对大家有参考作用。


python魔术方法有什么用


1、什么是魔法方法?

魔术方法是可以为你的类添加魔术的特殊方法。如果你的对象实现(重载)这些方法之一,则 Python 在特殊情况下将调用此方法。你可以定义自己想要的行为,这一切都会自动触发。它们通常用两个下划线命名(例如 __init__、__lt__)。 Python 的魔法方法非常强大,因此了解如何使用它们很重要!


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

(1) __init__ 构造函数,在创建实例时进行初始化的方法。但这不是实例化调用的第一个方法。 __new__ 是实例化对象调用的第一个方法。它只接受 cls 参数并将其他参数传递给 __init__。 __new__ 很少使用,但在某些情况下它是合适的,尤其是当类继承自不经常更改的类型(如元组或字符串)时。

(2)__new__ 使用时注意以下四点:

a、__new__ 是实例化对象时调用的第一个方法;

湾。它的第一个参数就是这个类,其他参数用来直接传递给__init__方法;

c、__new__ 返回一个构建的实例;

d。 __new__ 决定是否使用 __init__ 方法,因为 __new__ 可以调用其他类的构造函数,也可以直接返回其他实例对象作为该类的实例。如果 __new__ 不返回实例对象,则不会使用 __init__。转移;

e. __new__ 主要用于继承元组或字符串等不可变类型。

__new__ 实现了单例模式(不管实例化多少次,结果都是同一个实例)

单例模式是一种常见的软件设计模式,其主要目的是确保只存在一个类的实例。当你只希望一个类的一个实例出现在整个系统中时,单例对象会派上用场。

例如,服务端程序的配置信息存储在一个文件中,客户端通过AppConfig类读取配置文件信息。如果在程序运行过程中需要在很多地方使用配置文件的内容,也就是说需要在很多地方创建AppConfig对象的实例,从而导致在程序运行过程中存在多个AppConfig实例对象。系统,这将严重浪费内存资源,尤其是如果配置文件有很多内容。事实上,对于像 AppConfig 这样的类,我们希望在程序运行期间只存在一个对象实例。

举例:

class Person(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age
  def __new__(cls, *args, **kwargs):
    if not hasattr(cls,'instance'):
      cls.instance = super().__new__(cls)
    return cls.instance
a = Person('p1',21)
b = Person('p2',22)
print(a == b, a.name == b.name)    # 这里的打印结果都是True,可见 a 和 b 都是同一个实例(实例 b 覆盖了实例 a)。
# 单例作用:
  #第一、控制资源的使用,通过线程同步来控制资源的并发访问;
  #第二、控制实例产生的数量,达到节约资源的目的;
  #第三、作为通信媒介使用,也就是数据共享。比如,数据库连接池的设计一般采用单例模式,数据库连接是一种数据库资源。
# 应用场景:
  #Python的logger就是一个单例模式,用以日志记录
  #线程池、数据库连接池等资源池一般也用单例模式
  #Windows的资源管理器是一个单例模式
  #网站计数器

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


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

(1)__call__ 允许一个类的实例像函数一样被调用,如下:

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

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

class Person(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age
    self._registry = {
      'name': name,
      'age': age
    }
  def __call__(self, *args):
    return self.instance(*args)
  def __getitem__(self, key):
    if key not in self._registry.keys():
      raise Exception('Please registry the key:%s first !' % (key,))
    return self._registry[key]
a = Person('p1', 20)
print(a['name'],a['age'])
#这里打印的是 'p1' 20
#可见__getitem__使实例可以像字典一样访问

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


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

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

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

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

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

class Person(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age
    self._registry = {
      'name': name,
      'age': age
    }
  def __getattribute__(self, item):
    #注意此处不要再访问属性,如self.__dict__[item]
    #因为self.__dict__依然会被__getattribute__拦截,这样就会陷入死循环
    return object.__getattribute__(self,item)
  def __getattr__(self, item):
    print("don't have the attribute ",item)
    return False
  def __setattr__(self, key, value):
    self.__dict__[key] = value
a = Person('p1', 20)
print(a.cs)      #这里会打印 don't have the attribute cs 以及 False
a.cs = '测试'     #这里设置该属性值为'测试'
print(a.cs)      #这里将打印出'测试'

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

知行编程网
知行编程网 关注:1    粉丝:1
这个人很懒,什么都没写
扫一扫二维码分享