# python两组概念辨析:__getitem__ .vs. getitem & __getattr__ .vs. getattr
## 内容
在 Python 中,`__getitem__`、`__getattr__`、`getitem` 和 `getattr` 都是与对象属性访问和方法相关的概念,但是它们的作用和使用场景有很大的区别。下面我将详细分析它们之间的区别,并解释哪些是 Python 特有的。
### 1. `__getitem__` vs `getitem`
#### `__getitem__`
`__getitem__` 是 Python 中的一个特殊方法(也叫魔法方法或 dunder 方法),用于访问对象的元素。当你使用 `obj[key]` 这种语法时,Python 会调用对象的 `__getitem__` 方法来返回对应的元素。
- **用途**:当你想让一个对象支持像列表、字典、元组那样通过索引或键来访问其元素时,就需要实现 `__getitem__`。
- **示例**:
```python
class MyList:
def __init__(self, data):
self.data = data
def __getitem__(self, index):
return self.data[index]
my_list = MyList([1, 2, 3])
print(my_list[1]) # 输出: 2
```
- 在上面的例子中,`obj[1]` 会触发调用 `obj.__getitem__(1)`,返回列表的第 2 个元素。
#### `getitem`
`getitem` 不是 Python 的内置方法或特殊方法。它可能是你自己在代码中定义的一个函数,也可能是某些库的函数名称,和 `__getitem__` 没有直接关系。一般情况下,如果你看到 `getitem`,它可能是某个函数或工具方法的名称,但它不是 Python 的内建功能。
```python
def getitem(obj, index):
return obj[index] # 通过 __getitem__ 调用
```
总结:
- `__getitem__` 是特殊方法,用于实现通过索引访问元素。
- `getitem` 是普通的函数名称,通常由用户定义,不是 Python 内置的特殊方法。
### 2. `__getattr__` vs `getattr`
#### `__getattr__`
`__getattr__` 是 Python 中的另一个特殊方法。它在访问不存在的属性时被调用。只有当你访问一个对象的属性,而这个属性不存在时,Python 才会调用 `__getattr__`。
- **用途**:通过 `__getattr__` 可以定制对象的属性访问行为,通常用于延迟加载或动态创建属性。
- **示例**:
```python
class MyClass:
def __init__(self):
self.existing_attr = "I exist"
def __getattr__(self, name):
return f"Attribute {name} not found"
obj = MyClass()
print(obj.existing_attr) # 输出: I exist
print(obj.non_existing_attr) # 输出: Attribute non_existing_attr not found
```
- 在上面的例子中,当访问 `non_existing_attr` 时,Python 会调用 `__getattr__`,返回一个自定义的值。
#### `getattr`
`getattr` 是 Python 的内置函数,用于访问对象的属性。它的作用与 `obj.__getattr__(name)` 类似,但是 `getattr` 是一个普通函数,你可以显式地调用它,而不是依赖于 Python 自动触发。
- **用途**:`getattr` 用来安全地访问对象的属性,避免因属性不存在而抛出异常。它还可以提供一个默认值,如果属性不存在,则返回该默认值。
- **示例**:
```python
class MyClass:
def __init__(self):
self.existing_attr = "I exist"
obj = MyClass()
print(getattr(obj, 'existing_attr', 'Default Value')) # 输出: I exist
print(getattr(obj, 'non_existing_attr', 'Default Value')) # 输出: Default Value
```
- `getattr(obj, 'non_existing_attr', 'Default Value')` 先尝试获取 `obj` 的 `non_existing_attr` 属性,如果该属性不存在,返回 `'Default Value'`。
总结:
- `__getattr__` 是特殊方法,用于访问不存在的属性。
- `getattr` 是内置函数,用于安全地访问属性并提供默认值。
### 3. 总结
| 名称 | 用法 | 触发时机或用途 | 示例 |
|------------------|----------------------------------------|---------------------------------------------------|---------------------------------------------|
| `__getitem__` | 特殊方法,用于 `obj[key]` 语法访问元素 | 用于支持通过索引或键访问元素(例如字典、列表) | `obj.__getitem__(key)` |
| `getitem` | 普通函数或方法,不是 Python 内置的 | 可以作为普通函数定义,手动实现访问行为 | `getitem(obj, key)` |
| `__getattr__` | 特殊方法,用于访问不存在的属性 | 只有在访问一个对象的不存在属性时触发 | `obj.__getattr__(name)` |
| `getattr` | 内置函数 | 安全访问对象的属性,并可以提供默认值 | `getattr(obj, 'attr_name', 'default')` |
### 结论
- `__getitem__` 和 `__getattr__` 是 Python 的魔法方法,它们用于特定情况下的属性或元素访问。
- `getitem` 和 `getattr` 是普通的函数,`getitem` 不是 Python 内置的,而 `getattr` 是 Python 提供的内置函数。
希望这些解释帮助你理解它们之间的区别!