ZetCode

Python getattr 函数

上次修改时间:2025 年 4 月 11 日

这篇全面的指南探讨了 Python 的 getattr 函数,它提供了动态属性访问。 我们将涵盖基本用法、默认值、方法调用和动态属性查找的实际示例。

基本定义

getattr 函数返回对象的指定名称属性的值。 如果该属性不存在,它将返回默认值或引发 AttributeError。

主要特征:接受一个对象、属性名称字符串和一个可选的默认值。 它是 Python 内置的在运行时动态访问属性的方式。

基本属性访问

这是一个简单的用法示例,展示了 getattr 如何像点符号一样访问对象属性,但使用动态属性名称。

basic_getattr.py
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person("Alice", 30)

# Standard attribute access
print(p.name)  # Alice

# Using getattr
print(getattr(p, 'name'))  # Alice
print(getattr(p, 'age'))   # 30

此示例显示了访问属性的等效方法。 getattr 版本允许在运行时将属性名称确定为字符串。

虽然点符号是已知属性的首选方法,但 getattr 实现了动态属性查找,这对于灵活的代码来说非常强大。

处理缺失属性

当属性不存在时,getattr 可以提供默认值,从而防止 AttributeError 异常。 此示例演示了安全的属性访问。

default_value.py
class Config:
    def __init__(self):
        self.theme = "dark"
        self.font_size = 12

config = Config()

# Safe access with default
print(getattr(config, 'theme', 'light'))      # dark (exists)
print(getattr(config, 'language', 'en'))      # en (default)
print(getattr(config, 'font_size', 14))       # 12 (exists)

当属性存在时,getattr 返回其值。 当它不存在时,它会返回默认值,而不是引发错误。

这种模式对于配置系统非常有用,在配置系统中,缺失的设置应回退到默认值,而不会使程序崩溃。

动态方法调用

getattr 可以动态检索方法,从而可以在运行时确定要调用的方法。 此示例显示了多态行为。

method_calling.py
class Calculator:
    def add(self, a, b):
        return a + b
    
    def subtract(self, a, b):
        return a - b
    
    def execute(self, operation, a, b):
        method = getattr(self, operation)
        return method(a, b)

calc = Calculator()
print(calc.execute('add', 5, 3))        # 8
print(calc.execute('subtract', 5, 3))   # 2

execute 方法使用 getattr 根据操作名称字符串动态选择要调用的操作方法。

这种技术在命令模式实现和插件系统中很常见,在这些系统中,行为是在运行时确定的。

访问嵌套属性

getattr 可以与其他 Python 功能结合使用,以动态访问嵌套属性。 此示例显示了深度属性访问。

nested_attributes.py
class Address:
    def __init__(self, city):
        self.city = city

class User:
    def __init__(self, name, address):
        self.name = name
        self.address = address

addr = Address("New York")
user = User("Bob", addr)

# Dynamically access nested attribute
attr_path = 'address.city'
parts = attr_path.split('.')
result = user
for part in parts:
    result = getattr(result, part)

print(result)  # New York

此代码拆分一个点分隔的属性路径,并在循环中使用 getattr 来遍历嵌套对象。 它类似于 Django 的 ORM 的工作方式。

对于生产代码,您需要为路径中任何级别的缺失属性添加错误处理。

实现回退机制

当与 __getattr__ 结合使用时,getattr 可用于实现复杂的回退机制。 此示例显示了代理模式。

fallback.py
class DataProxy:
    def __init__(self, data):
        self._data = data
    
    def __getattr__(self, name):
        # Try to get from _data first, then use default
        try:
            return getattr(self._data, name)
        except AttributeError:
            return f"Default {name}"

class Data:
    def __init__(self, value):
        self.value = value

data = Data(42)
proxy = DataProxy(data)

print(proxy.value)      # 42 (from _data)
print(proxy.unknown)    # Default unknown

代理首先尝试从包装对象获取属性,然后回退到默认值。 这演示了 getattr 在 Python 属性查找链中的作用。

这种模式对于需要转发大多数属性访问的装饰器、适配器和其他代理对象非常有用。

最佳实践

资料来源

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程