魔术方法 #
魔术方法(Magic Methods)是具有特殊功能的一组方法,它们在特定的操作或事件发生时被自动调用。这些方法通常以双下划线(__)开头和结尾
构造和初始化:
__new__(cls)__
: 创建并返回新对象,__new__
先于__init__
被调用,通常用于控制对象的创建过程__init__(self, ...)
: 构造函数,用于控制对象的初始化过程。每当一个类被实例化时,__init__
会被自动调用__del__(self)
: 析构函数,在对象被销毁之前调用。用于清理资源,如文件句柄、数据库连接等
__new__
是静态类方法,__init__
是实例方法,sefl作为参数,一般返回None。除了为了继承不可变类型如int、str、tuple或unicode类型外,一般不需要 override__new__
方法
表示和打印:
__str__(self)
: 返回对象的可打印字符串。被print()
函数、str()
调用__repr__(self)
: 返回对象的“官方”字符串表示。被 repr() 调用,或在交互式解释器中显示对象时使用__len__(self)
: 返回对象的长度。当调用 len() 函数时,Python 会自动调用此方法
python
Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 19 2020, 20:48:48)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import uuid
>>> uuid.uuid1()
UUID('12729d40-c1d1-11ef-8c95-acde48001122')
>>> a = uuid.uuid1()
>>> print(a)
15403328-c1d1-11ef-8a1d-acde48001122
>>>
比较操作:
__eq__(self, other)
/__ge__
/__le__
/__lt__
/__gt__
/__ne__
:==
/>=
/<=
/<
/>
/!=
算术操作:
__add__(self, other)
/__sub__
/__mul__
: 实现加法+
/-
/*
运算__truediv__(self, other)
: 实现除法/
运算__floordiv__(self, other)
: 实现地板除法//
运算__mod__(self, other)
: 实现取余%
运算__pow__(self, other)
: 实现幂运算**
__matmul__(self, other)
: 实现矩阵乘法@
,第三方类似numpy
支持//
为地板除法,返回不比原结果大的第一个整数,所以-4 // 3 == -2
,4 // 3 == 1
容器协议:
__getitem__(self, key)
: 获取索引 key 对应的元素,支持obj[key]
语法__setitem__(self, key, value)
: 设置索引 key 对应的元素,支持obj[key] = value
语法__delitem__(self, key)
: 删除索引 key 对应的元素,支持del obj[key]
语法__iter__(self)
: 返回一个迭代器对象__next__(self)
: 返回迭代器的下一个元素__contains__(self, item)
: 检查 item 是否在对象中,支持item in obj
语法
属性访问:
__getattr__(self, name)
: 当访问对象中不存在的属性时被调用__setattr__(self, name, value)
: 设置对象的属性时被调用__delattr__(self, name)
: 删除对象的属性时被调用
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __getattr__(self, name):
print(f"Attribute '{name}' does not exist!")
return f"'{name}' is not a valid attribute."
def __setattr__(self, name, value):
print(f"Setting attribute '{name}' to '{value}'")
super().__setattr__(name, value)
person = Person("Alice", 30)
print(person.name) # Alice
print(person.age) # 30
print(person.gender) # Attribute 'gender' does not exist!
# 'gender' is not a valid attribute.
person.gender = 'male' # Setting attribute 'gender' to 'male'
上下文管理器:
__enter__(self)
: 在 with 语句块开始时调用__exit__(self, exc_type, exc_val, exc_tb)
: 在 with 语句块结束时调用,用于处理异常或清理工作,exc_type = exception class
/exc_value = exception instance
/exc_tb = error traceback
with open("/etc/hosts", "r") as f: print(f.read())
import threading # 全局计数器 counter = 0 # 创建一个锁对象 lock = threading.Lock() # 定义一个线程要执行的任务 def increment_counter(): global counter for _ in range(100000): with lock: # 使用锁保护对共享资源的访问 # 包含读取和修改2个非原子操作,不加锁会导致race conditions不同线程同时读取到相同的counter值,导致数据丢失 counter += 1 # 创建多个线程 threads = [] for _ in range(5): # 创建 5 个线程 thread = threading.Thread(target=increment_counter) threads.append(thread) # 启动所有线程 for thread in threads: thread.start() # 等待所有线程完成 for thread in threads: thread.join() print(f"Final counter value: {counter}") # 500000
import sqlite3 with sqlite3.connect("test.db") as conn: # cursor 提供了一种遍历查询结果集的抽象机制,可以视为一个指针,每次指向多行数据的一行,就是类似终端中的光标 # create table 一般不需要cursor,但是python需要,是一种概念上的overhead # https://stackoverflow.com/questions/6318126/why-do-you-need-to-create-a-cursor-when-querying-a-sqlite-database cursor = conn.cursor() cursor.execute("CREATE TABLE IF NOT EXISTS books (title TEXT, pages INTEGER)") cursor.execute("INSERT INTO books VALUES ('The Catcher in the Rye', 234)") cursor.execute("INSERT INTO books VALUES ('1984', 328)") cursor.execute("INSERT INTO books VALUES ('To Kill a Mockingbird', 281)") cursor.execute("SELECT * FROM books") books = cursor.fetchall() for book in books: print(book)
import socket with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect(("www.example.com", 80)) s.sendall(b"GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n") response = s.recv(4096) print(response) print(response.decode("utf-8"))
import os with os.scandir(".") as entries: for entry in entries: print(entry.name)
import time class Timer: def __enter__(self): self.start_time = time.time() return self def __exit__(self, exc_type, exc_value, traceback): self.end_time = time.time() elapsed_time = self.end_time - self.start_time print(f"Elapsed time: {elapsed_time} seconds") with Timer() as timer: time.sleep(2) # Elapsed time: 2.003740072250366 seconds
其他:
__wrapped__
: 主要用于访问装饰器包装的函数的原始版本__call__(self, ...)
: 使对象能够像函数一样被调用。当执行obj()
时,会调用obj.__call__()
__reversed__(self)
: 返回对象的反向迭代器,支持reversed(obj)
__index__(self)
: 返回对象的整数索引,obj[index]
/range
__copy__(self)
: 对象的浅复制(浅拷贝)__deepcopy__(self, memo)
: 对象的深复制(深拷贝),memo字典存放已经被copy的对象,避免循环创建memo[id(self)] = new_copy
,有点像visited
字典