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号