Python魔术方法

本文深入介绍了Python中的魔术方法,包括对象实例化、比较、运算符重载等,并提供了多个示例,如文件对象管理和单词比较类等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考文章:

Python 魔术方法指南

魔术方法,顾名思义是一种可以给对象(类)增加魔法的特殊方法,它们的表示方法一般是用双下划线包围(如__init__)

对象实例化

from os.path import join

class FileObject:
    '''给文件对象进行包装从而确认在删除时文件流关闭'''

    def __init__(self, filepath='~', filename='sample.txt'):
        #读写模式打开一个文件
        self.file = open(join(filepath, filename), 'r+')

    def __del__(self):
        self.file.close()
        del self.file
  • __new__(cls, [...]): 在一个对象实例化调用的第一个方法,第一个参数是类,剩下的参数传递给__init__

  • __init__(self, [...]): 类的初始化方法。当构造函数被调用的时候的任何参数够会传给它

  • __del__(self): __new____init__为对象的构造器,__del__为对象的析构器。当一个对象进行过垃圾回收时候的行为就是这个方法。当一个对象在删除的时候需要更多的清洁工作,就需要使用这个方法

比较

class Word(str):
'''存储单词的类,定义比较单词的几种方法'''

    def __new__(cls, word):
        # 注意我们必须要用到__new__方法,因为str是不可变类型
        # 所以我们必须在创建的时候将它初始化
        if ' ' in word:
            print("Value contains spaces. Truncating to first space.")
            word = word[:word.index(' ')] #单词是第一个空格之前的所有字符
        return str.__new__(cls, word)

    def __gt__(self, other):
        return len(self) > len(other)
    def __lt__(self, other):
        return len(self) < len(other)
    def __ge__(self, other):
        return len(self) >= len(other)
    def __le__(self, other):
        return len(self) <= len(other)
  • __cmp__(self, other): 用于比较的魔术方法,实现了所有的比较符号。如果self < other返回一个负数;如果self == other返回0;如果self > other返回正数。一般情况下是分别定义每一个比较符号。如果想实现所有的比较符号,就需要调用这个方法。

  • __eq__(self, other): 等号

  • __ne__(self, other): 不等号
  • __lt__(self, other): 小于
  • __gt__(self, other): 大于
  • __le__(self, other): 小于等于
  • __ge__(self, other): 大于等于

一元操作符和函数

  • __pos__(self):实现正号的特性
  • __neg__(self):实现负号的特性
  • __abs__(self):abs, 绝对值
  • __invert__(self):实现~的特性

普通算数操作符

  • __add__(self, other): 实现加法
  • __sub__(self, other): 实现减法
  • __mul__(self, other): 实现乘法
  • __floordiv__(self, other): 实现整除法
  • __div__(self, other): 实现除法
  • __mod__(self, other): 实现取模
  • __pow__(self, other): 实现指数
  • __lshift__(self, other): 实现<<
  • __rshift__(self, other): 实现>>
  • __and__(self, other): 实现&
  • __or__(self, other): 实现|
  • __xor__(self, other): 实现^

其他

def __setattr__(self, name, value):
    self.name = value
    #每当属性被赋值的时候, ``__setattr__()`` 会被调用,这样就造成了递归调用。
    #这意味这会调用 ``self.__setattr__('name', value)`` ,每次方法会调用自己。这样会造成程序崩溃。

def __setattr__(self, name, value):
    self.__dict__[name] = value  #给类中的属性名分配值
    #定制特有属性
class AccessCounter:
    '''一个包含计数器的控制权限的类每当值被改变时计数器会加一'''

    def __init__(self, val):
        super(AccessCounter, self).__setattr__('counter', 0)
        super(AccessCounter, self).__setattr__('value', val)

    def __setattr__(self, name, value):
        if name == 'value':
            super(AccessCounter, self).__setattr__('counter', self.counter + 1)
    #如果你不想让其他属性被访问的话,那么可以抛出 AttributeError(name) 异常
        super(AccessCounter, self).__setattr__(name, value)

    def __delattr__(self, name):
        if name == 'value':
            super(AccessCounter, self).__setattr__('counter', self.counter + 1)
        super(AccessCounter, self).__delattr__(name)]
  • __str__(self): 返回值,人类可读

  • __repr__(self): 返回值,机器可读

  • __unicode__(self): 返回unicode()

  • __hash__(self): hash()返回一个整形

  • __nonzero__(self): bool()返回的值

  • __getattr__(self, name): 当用户试图获取一个不存在(或不建议的属性)的属性时,给出一些警告

  • __setattr__(self, name, value): 无论属性是否存在,都允许你定义对属性的赋值行为

  • __delattr__(self, name): 删除一个属性

封装附加魔术方法

class FunctionalList:
'''一个封装了一些附加魔术方法比如 head, tail, init, last, drop, 和take的列表类。
'''

    def __init__(self, values=None):
        if values is None:
            self.values = []
        else:
            self.values = values

    def __len__(self):
        return len(self.values)

    def __getitem__(self, key):
        #如果键的类型或者值无效,列表值将会抛出错误
        return self.values[key]

    def __setitem__(self, key, value):
        self.values[key] = value

    def __delitem__(self, key):
        del self.values[key]

    def __iter__(self):
        return iter(self.values)

    def __reversed__(self):
        return reversed(self.values)

    def append(self, value):
        self.values.append(value)
    def head(self):
        return self.values[0]
    def tail(self):
        return self.values[1:]
    def init(self):
        #返回一直到末尾的所有元素
        return self.values[:-1]
    def last(self):
        #返回末尾元素
        return self.values[-1]
    def drop(self, n):
        #返回除前n个外的所有元素
        return self.values[n:]
    def take(self, n):
        #返回前n个元素
        return self.values[:n]

反射

  • __instancecheck__(self, instance): 检查一个实例是否为定义类的实例
  • __subclasscheck__(self, subclass): 检查一个类是否为定义类的子类

更改状态

  • __call__(self, [...]): 经常改变状态的时候,调用这个方法是一种直接和优雅的方法
class Entity:
'''调用实体来改变实体的位置。'''

    def __init__(self, size, x, y):
        self.x, self.y = x, y
        self.size = size

    def __call__(self, x, y):
        '''改变实体的位置'''
        self.x, self.y = x, y

会话管理

使用with语句来调用

class Closer:
'''通过with语句和一个close方法来关闭一个对象的会话管理器'''

    def __init__(self, obj):
        self.obj = obj

    def __enter__(self):
        return self.obj # bound to target

    def __exit__(self, exception_type, exception_val, trace):
        try:
            self.obj.close()
        except AttributeError: # obj isn't closable
            print('Not closable.')
        return True # exception handled successfully

__slots__

限制class的属性,但不限制class的子类的属性,除非子类也使用__slots__

例子:

使用__slots__会比不使用,减少40%~50%的内存

# 不使用__slots__
class MyClass(object):
  def __init__(self, name, identifier):
      self.name = name
      self.identifier = identifier
      self.set_up()

# 使用__slots__
class MyClass(object):
  __slots__ = ['name', 'identifier']
  def __init__(self, name, identifier):
      self.name = name
      self.identifier = identifier
      self.set_up()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值