共计 4643 个字符,预计需要花费 12 分钟才能阅读完成。
什么是反射?
在 Python 中,反射是指通过一组内置的函数和语句,在运行时动静地拜访、检查和批改对象的属性、办法和类信息的机制。Python 中的反射机制十分弱小,能够使程序更加灵便和可扩大。
Python 中的反射次要波及以下几个内置函数和语句:
- getattr():获取对象的属性或办法。能够通过对象和字符串的形式传递属性或办法名,并且还能够提供一个默认值,用于在属性或办法不存在时返回。
- setattr():设置对象的属性或办法。能够通过对象、字符串和值的形式传递属性或办法名和值。
- delattr():删除对象的属性或办法。能够通过对象和字符串的形式传递属性或办法名。
- dir():获取对象的所有属性和办法的列表。能够应用 dir() 函数来获取对象的所有属性和办法的列表。
- type():获取对象的类型。能够应用 type() 函数来获取对象的类型信息。
- inspect 模块:该模块提供了更加高级的反射性能,能够用于获取函数和类的参数列表、注解、源代码等信息。
利用场景
反射在 Python 中的利用场景十分宽泛,例如:
- 动静加载模块和类:应用反射能够在运行时动静加载模块和类,以便于程序更加灵便和可扩大。
- 动静批改对象属性和办法:应用反射能够在运行时动静批改对象的属性和办法,以便于程序更加灵便。
- 实现插件零碎:应用反射能够实现插件零碎,容许程序在运行时动静加载和卸载插件。
- 实现 ORM 框架:应用反射能够实现 ORM 框架,容许程序在运行时动静地将 Python 对象映射到数据库中的表格。
总之,反射是 Python 中一种十分有用的元编程技术,能够使程序更加灵便和可扩大。然而,在应用反射时须要审慎,防止滥用,因为反射可能会影响性能并减少代码复杂度。
根本小栗子
- 拜访对象属性
class MyClass: | |
def __init__(self, x): | |
self.x = x | |
obj = MyClass(42) | |
attr_name = "x" | |
attr_value = getattr(obj, attr_name) | |
print(f"{attr_name} = {attr_value}") |
- 动静调用对象办法
class MyClass: | |
def my_method(self, x, y): | |
return x + y | |
my_object = MyClass() | |
result = getattr(my_object, "my_method")(1, 2) | |
print(result) # 输入 3 |
- 动静创建对象
class MyClass: | |
def __init__(self, x, y): | |
self.x = x | |
self.y = y | |
my_class = type("MyClass", (), {"x": 1, "y": 2}) | |
my_object = my_class() | |
print(my_object.x, my_object.y) # 输入 1 2 |
- 动静导入模块
# 应用 importlib.import_module() 导入模块 | |
import importlib | |
module_name = 'math' | |
module = importlib.import_module(module_name) | |
# 应用 getattr() 拜访模块的属性 | |
pi_value = getattr(module, 'pi') | |
print(pi_value) # 输入: 3.141592653589793 |
- 获取类属性
class MyClass: | |
my_class_attribute = "Hello World" | |
print(getattr(MyClass, "my_class_attribute")) # 输入 "Hello World" |
- 查看对象是否具备属性
class MyClass: | |
def __init__(self): | |
self.my_attribute = "Hello World" | |
my_object = MyClass() | |
print(hasattr(my_object, "my_attribute")) # 输入 True | |
print(hasattr(my_object, "non_existent_attribute")) # 输入 False |
- 动静获取类的办法列表
class MyClass: | |
def __init__(self): | |
self.my_attribute = 'Hello, World!' | |
def my_method(self): | |
print(self.my_attribute) | |
# 应用 dir() 获取类的办法列表 | |
method_list = [method_name for method_name in dir(MyClass) if callable(getattr(MyClass, method_name))] | |
print(method_list) # 输入: ['__init__', '__module__', 'my_method'] |
- 动静调用模块中的函数
# 应用 importlib.import_module() 导入模块 | |
import importlib | |
module_name = 'math' | |
module = importlib.import_module(module_name) | |
# 应用 getattr() 拜访模块中的函数 | |
sqrt_function = getattr(module, 'sqrt') | |
result = sqrt_function(4) | |
print(result) # 输入: 2.0 |
- 动静批改对象的属性
class MyClass: | |
def __init__(self): | |
self.my_attribute = 'Hello, World!' | |
my_object = MyClass() | |
# 应用 setattr() 批改对象的属性 | |
setattr(my_object, 'my_attribute', 'Hello, Universe!') | |
print(my_object.my_attribute) # 输入: 'Hello, Universe!' |
贴近理论利用的小场景
假如正在构建一个电商网站,并须要实现一个订单管理系统。这个零碎须要反对多种订单类型(例如一般订单、抢购订单、团购订单等),每种订单类型有其独特的属性和办法。
为了实现这个零碎,能够应用反射来动静地创立订单对象,并依据订单类型来调用相应的属性和办法。
首先,须要定义一个根本的订单类,该类蕴含所有订单类型的通用属性和办法。而后,能够创立一个名为 OrderFactory 的工厂类,该类负责依据订单类型创立订单对象。
上面是示例代码:
class Order: | |
def __init__(self, order_id, customer_name, product_id): | |
self.order_id = order_id | |
self.customer_name = customer_name | |
self.product_id = product_id | |
def calculate_total_price(self): | |
# 计算订单总价 | |
pass | |
def validate_order(self): | |
# 验证订单是否非法 | |
pass | |
def confirm_order(self): | |
# 确认订单 | |
pass | |
class OrderFactory: | |
@staticmethod | |
def create_order(order_type, order_id, customer_name, product_id): | |
# 动态创建订单对象 | |
order_class = globals().get(order_type) | |
if not order_class: | |
raise ValueError(f"Invalid order type: {order_type}") | |
return order_class(order_id, customer_name, product_id) | |
class FlashSaleOrder(Order): | |
def __init__(self, order_id, customer_name, product_id, discount): | |
super().__init__(order_id, customer_name, product_id) | |
self.discount = discount | |
def calculate_total_price(self): | |
# 计算限时抢购订单的总价(蕴含折扣)pass | |
class GroupBuyOrder(Order): | |
def __init__(self, order_id, customer_name, product_id, group_size): | |
super().__init__(order_id, customer_name, product_id) | |
self.group_size = group_size | |
def calculate_total_price(self): | |
# 计算团购订单的总价(依据购买人数和商品单价)pass |
当初,能够应用 OrderFactory 来创立订单对象。例如,要创立一个限时抢购订单,能够应用以下代码:
order_type = "FlashSaleOrder" | |
order_id = "123" | |
customer_name = "Alice" | |
product_id = "456" | |
discount = 0.2 | |
order = OrderFactory.create_order(order_type, order_id, customer_name, product_id, discount) |
这将动静地创立一个 FlashSaleOrder 对象,并应用提供的参数初始化它。
另外,如果须要动静调用订单对象的办法,能够应用 Python 的内置反射机制。例如,要调用订单对象的 calculate_total_price 办法,能够应用以下代码:
method_name = "calculate_total_price" | |
method = getattr(order, method_name) | |
total_price = method() |
这将动静地获取 order 对象的 calculate_total_price 办法,并调用它来计算订单的总价。
本文转载于公众号不背锅运维:https://mp.weixin.qq.com/s/NRSkzdAbcdF828YhFd88NA