Python魔力方法
Python的魔术方法(Magic Methods)也称为双下划线方法(double underscore method),以双下划线开头和结尾,用于重载类的特殊行为。可以使类的实例对象表现出像内置类型的行为,如加、减、乘、切片、比较等,增加代码的可读性和可维护性。以下是Python中一些重要的魔术方法:
1.__init__方法
__init__(self[, ...])方法在创建类的实例对象时自动调用,用于进行初始化操作,为实例对象的属性设置初始值。其中,self代表实例对象本身。此外,__new__方法在创建类的实例对象之前被调用,可以用来进行一些定制化的操作。
示例:
class MyClass:
    def __init__(self, name):
        self.name = name
obj = MyClass("Tom")
print(obj.name)  # 输出 Tom
2.__call__方法
__call__(self[, ...])方法使得对象可以像函数一样被调用,用于对实例对象添加可调用特性。一般情况下,Python中的函数即对象,而__call__方法可以让实例对象也表现得像函数。
示例:
class MyClass:
    def __call__(self):
        print("Hello, I can be called like a function.")
obj = MyClass()
obj()  # 输出:Hello, I can be called like a function.
3.__str__和__repr__方法
__str__(self)方法返回一个字符串,用于自定义实例对象的字符串输出格式。__repr__(self)方法也返回一个字符串,表示对实例对象进行计算或操作的表达式或字符串,通常被用于调试和日志输出。
示例:
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __str__(self):
        return f"{self.name}, {self.age} years old."
    def __repr__(self):
        return f"Person(name={self.name}, age={self.age})"
p = Person("Tom", 18)
print(str(p))  # 输出:Tom, 18 years old.
print(repr(p))  # 输出:Person(name=Tom, age=18)
4.__add__、__sub__、__mul__、__div__(加减乘除)
__add__(self, other)方法表示“加”,用于定义对象的加法行为,self代表第一个加数,other代表第二个加数。类似的,有__sub__、__mul__、__div__等方法表示减、乘、除等。
示例:
class Vector:
    def __init__(self, x=None, y=None):
        self.x = x
        self.y = y
    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x, y)
    def __str__(self):
        return f"({self.x}, {self.y})"
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)  # 输出:(4, 6)
5.__len__方法
__len__(self)方法用于定义实例对象的长度,返回一个整数,即对象中元素的数量。常用于定制容器类型的大小。
示例:
class MyClass:
    def __init__(self, lst=None):
        self.lst = lst
    def __len__(self):
        return len(self.lst)
obj = MyClass([1, 2, 3])
print(len(obj))  # 输出:3
6.__getitem__、__setitem__和__delitem__方法
__getitem__(self, key)方法和__setitem__(self, key, value)方法定义了实例对象的索引和切片功能,__delitem__(self, key)方法用于实现删除操作。其中,key表示索引或切片范围,value表示要赋值的值。
示例:
class MyList:
    def __init__(self, lst=None):
        self.lst = lst if lst else []
    def __getitem__(self, index):
        return self.lst[index]
    def __setitem__(self, index, value):
        self.lst[index] = value
    def __delitem__(self, index):
        del self.lst[index]
    def __len__(self):
        return len(self.lst)
lst = MyList([1, 2, 3])
print(lst[1])   # 输出:2
lst[1] = 5
print(lst[1])   # 输出:5
del lst[0]
print(len(lst))  # 输出:2
7.__iter__和__next__方法
__iter__(self)方法返回一个可迭代对象,用于定义实例对象的迭代行为。__next__(self)方法用于定义实例对象的下一个元素是什么,具体包括迭代开始、迭代状态以及迭代结束时所需的返回值。
示例:
class Fibonacci:
    def __init__(self, n):
        self.n = n
        self.current = 0
        self.next = 1
    def __iter__(self):
        return self
    def __next__(self):
        if self.current + self.next > self.n:
            raise StopIteration
        self.current, self.next = self.next, self.current + self.next
        return self.current
for i in Fibonacci(100): 
    print(i, end=' ')  # 输出:1 1 2 3 5 8 13 21 34 55 89
8.__getattr__和__setattr__方法
__getattr__(self, attr)方法用于获取实例对象的属性,当代码中使用了实例对象没有的属性时,该方法会被调用,如果没有定义该方法,则会抛出AttributeError异常。__setattr__(self, attr, value)方法用于设置实例对象的属性,当代码中设置实例对象没有的属性时,该方法会被调用。
示例:
class MyClass:
    def __init__(self, name):
        self.name = name
    def __getattr__(self, attr):
        return f"{attr} 属性不存在。"
    def __setattr__(self, attr, value):
        if attr == "name":
            self.__dict__[attr] = value.upper()
        else:
            self.__dict__[attr] = value
obj = MyClass("Tom")
print(obj.name)  # 输出:TOM
print(obj.age)   # 输出:age 属性不存在。
9.__enter__和__exit__方法
__enter__(self)方法会在进入with语句时被调用,用于进行一些初始化操作,同时该方法需要返回一个上下文管理器对象。__exit__(self, exc_type, exc_value, traceback)方法会在离开with语句时被调用,用于进行一些清理操作。
示例:
class File:
    def __init__(self, filename):
        self.filename = filename
    def __enter__(self):
        self.f = open(self.filename, "r")
        return self.f
    def __exit__(self, exc_type, exc_value, traceback):
        self.f.close()
with File("test.txt") as f:
    content = f.read()
    print(content)
10.__eq__、__lt__、__le__等比较方法
__eq__(self, other)方法用于定义等于运算符==,__lt__(self, other)、__le__(self, other)、__gt__(self, other)、__ge__(self, other)方法分别用于定义小于、小于等于、大于、大于等于运算符。
示例:
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __eq__(self, other):
        return self.age == other.age
    def __lt__(self, other):
        return self.age < other.age
p1 = Person("Tom", 18)
p2 = Person("Jerry", 20)
print(p1 == p2)  # 输出:False
print(p1 < p2)   # 输出:True
11.__hash__和__call__方法
__hash__(self)方法定义了实例对象的hash值,通常用于优化字典、集合等操作。__call__(self)方法定义了实例对象的调用过程,用于将实例对象作为函数调用时的行为。
示例:
class MyClass:
    def __init__(self, attr):
        self.attr = attr
    def __hash__(self):
        return hash(self.attr)
    def __call__(self):
        print(f"The attribute is {self.attr}.")
obj1 = MyClass(1)
obj2 = MyClass(2)
print(hash(obj1))  # 输出:1
print(hash(obj2))  # 输出:2
obj1()  # 输出:The attribute is 1.
12.__format__方法
__format__(self, format_spec)方法用于自定义实例对象的格式化,其中format_spec为格式化字符串。
示例:
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __format__(self, format_spec):
        if format_spec == "r":
            return f"({self.y}, {self.x})"
        else:
            return f"({self.x}, {self.y})"
p = Point(1, 2)
print(format(p))    # 输出:(1, 2)
print(format(p, "r"))  # 输出:(2, 1)
13.__dir__方法
__dir__(self)方法用于自定义类的dir()函数返回的属性列表,默认情况下会返回类的所有属性和方法,包括从父类继承的。
示例:
class MyClass:
    def __init__(self, name):
        self.name = name
    def foo(self):
        pass
    def __dir__(self):
        return [attr for attr in dir(self.__class__) if not attr.startswith("__")]
obj = MyClass("Tom")
print(dir(obj))  # 输出:['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'foo', 'name']
在上述示例中,__dir__方法返回了类的所有属性和方法,但排除了以__开头的魔术方法。
14.__init_subclass__方法
__init_subclass__(cls, **kwargs)方法在每个子类被创建时被调用,通常用于对子类进行初始化或配置。
示例:
class BaseClass:
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        print(f"Creating subclass {cls.__name__}")
class SubClass1(BaseClass):
    pass
class SubClass2(BaseClass):
    pass
# 输出:Creating subclass SubClass1
#       Creating subclass SubClass2
在上述示例中,当子类SubClass1和SubClass2被创建时,会自动调用__init_subclass__方法,并输出相应的信息。
15.__set_name__方法
__set_name__(self, owner, name)方法在类的属性被设置时被调用,通常用于对属性进行验证或初始化。注意,该方法只在 Python 3.6 及以上版本中可用。
示例:
class Validator:
    def __set_name__(self, owner, name):
        self.name = name
    def __get__(self, obj, owner):
        return obj.__dict__[self.name]
    def __set__(self, obj, value):
        if value < 0:
            raise ValueError(f"{self.name} should be greater than 0.")
        obj.__dict__[self.name] = value
class MyClass:
    x = Validator()
obj = MyClass()
obj.x = 1
print(obj.x)  # 输出:1
obj.x = -1   # 抛出 ValueError 异常
在上述示例中,Validator类的__set_name__方法会将属性名保存在name属性中,然后通过__get__和__set__方法对属性进行访问和设置。这里通过设置x属性来演示__set_name__方法的应用,如果设置的值小于 0,则抛出ValueError异常。
16.__new__方法
__new__(cls, *args, **kwargs)方法是一个特殊的静态方法,用于创建类的实例对象,通常用于自定义类的实例化过程。该方法会返回创建的新实例对象,然后调用__init__方法进行初始化。
示例:
class Singleton:
    instance = None
    def __new__(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = super().__new__(cls, *args, **kwargs)
            return cls.instance
        else:
            return cls.instance
    def __init__(self, name):
        self.name = name
obj1 = Singleton("Tom")
obj2 = Singleton("Jerry")
print(obj1 == obj2)  # 输出:True
print(obj1.name)     # 输出:Tom
print(obj2.name)     # 输出:Tom
在上述示例中,Singleton类通过重写__new__方法,实现了单例模式,保证每次实例化时返回的都是同一个实例对象。
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号