魔法方法就是可以给你的类增加魔力的特殊方法,它们总被双下划线所包围,像这种格式:"__方法名__",这些方法很强大,充满魔力,可以让你实现很多功能。
使用dir()查看类的所有属性和方法
class A:passprint(dir(A))"""
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
"""
一、__doc__
表示类的描述信息,它通常被放置在类定义的第一行,并且被三引号("""
)包围。print(A.__doc__)打印出来的是其中的信息
class A:"""hello world"""def hello(self):print("Hello")print(A.__doc__)>>> hello world
二、__module__(读取使用的模块名)
返回定义该类的原始模块名
例如:如果一个类定义在名为my_module.py
的文件中,那么这个类的__module__
属性将会返回字符串'my_module'
。这表明类是在这个模块中定义的。
三、__class__(读取使用的类名)
返回对象的类
class MyClass:pass# 创建MyClass的一个实例
my_instance = MyClass()# 访问实例的__class__属性
print(my_instance.__class__) # 输出: <class '__main__.MyClass'>
四、__call__
允许一个类的实例像函数一样被调用。在类中定义__call__
方法。这个方法接受任意数量的参数,这些参数在实例被调用时传递给__call__
方法。
class Calculator:def __init__(self, initial_value=0):self.value = initial_valuedef __call__(self, *args, **kwargs):# 这里可以根据需要处理 *args 和 **kwargs# 例如,我们可以将所有的位置参数累加到 self.valuefor arg in args:self.value += arg# 处理关键字参数,例如,如果有一个关键字参数 'multiply'if 'multiply' in kwargs:self.value *= kwargs['multiply']return self.value# 法一:
# 创建Calculator类的实例
calc = Calculator(10)# 调用实例,传递任意数量的位置参数和关键字参数
result = calc(5, 3, multiply=2) # 10 + 5 + 3 = 18, then multiply by 2#法二:
result = Calculator(10)(5, 3, multiply=2)print(result) # 输出: 36
用途
-
工厂模式:
__call__
方法常用于实现工厂模式,其中类的实例负责创建其他对象。 -
装饰器:在装饰器模式中,
__call__
方法用于包装函数或方法,以添加额外的功能。 -
回调函数:在需要回调函数的场景中,
__call__
方法允许类的实例作为回调函数。 -
单例模式:
__call__
方法也可以用于实现单例模式,确保只创建类的单个实例。
五、__dict__
它是一个字典,包含了类或对象的所有属性和它们的值,这些属性是动态添加到实例上的,并且不是在类定义时就确定的。
class Person:def __init__(self, name, age):self.name = nameself.age = ageprint(Person.__dict__) # 输出: {'__module__': '__main__', '__init__': <function Person.__init__ at 0x0000022AFDF5D1F0>,
# '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}# 创建Person类的实例
person = Person("Alice", 30)# 访问实例的__dict__属性
print(person.__dict__) # 输出: {'name': 'Alice', 'age': 30}# 向实例添加新属性
person.gender = "Female"# 查看添加新属性后的__dict__
print(person.__dict__) # 输出: {'name': 'Alice', 'age': 30, 'gender': 'Female'}
dir():
dir()
返回一个包含对象的所有属性和方法的列表,包括那些继承自父类的属性和方法。- 它不仅包括实例属性,还包括类属性、内置属性和方法。
__dict__:
__dict__
只包含一个对象的实例属性,即那些在对象创建后添加到对象中的属性。- 它不包括类属性或者继承自父类的属性和方法。
__dict__
是一个字典对象,其中包含了实例属性的名称和值。
综上__dict__
是 dir()
的子集
六、__repr__
改变对象的字符串显示
__str__():打印实例对象时,返国自定义的字符串---输出是给用户看的
__repr__():输出是给程序员Dedbug看的
class Point:def __init__(self, x, y):self.x = xself.y = ydef __repr__(self):return f"Point({self.x}, {self.y})"# 创建Point类的实例
p = Point(1, 2)# 使用repr()函数或直接打印对象
print(repr(p)) # 输出: Point(1, 2)
print(p) # 输出: Point(1, 2),因为__str__没有定义,所以打印时也调用了__repr__
七、__getitem__
、__setitem__
和 __delitem__
允许对象模拟序列(如列表和元组)或映射(如字典)的行为。这些方法使得对象可以支持索引、切片和赋值操作。
class Sequence:def __init__(self, elements):self.elements = elementsdef __getitem__(self, index):return self.elements[index]def __setitem__(self, index, value):self.elements[index] = valuedef __delitem__(self, index):del self.elements[index]# 创建Sequence类的实例
seq = Sequence([1, 2, 3, 4, 5])# 使用__getitem__方法,会自动触发
print(seq[0]) # 输出: 1# 使用__setitem__方法,会自动触发
seq[0] = 10
print(seq.elements) # 输出: [10, 2, 3, 4, 5]# 使用__delitem__方法,会自动触发
del seq[0]
print(seq.elements) # 输出: [2, 3, 4, 5]