概述、历史时间线、问题与解决方案
Python 类实例概述
什么是 Python 类实例?
你使用类来描述某个事物应该如何工作。当你调用这个类时,你创建了一个类实例。Python 类实例是由类生成的对象。它拥有自己存储值和执行操作的空间。
当你写 Dog() 时,你调用了 Dog 类。Python 执行 __init__ 方法来初始化这个对象。结果是一个新的类实例。你可以将其存储在一个名称下,例如 my_dog。你可以给它赋值,比如 my_dog.name = "Spot"。
Python 允许你通过调用类来创建新对象。
class Dog:
    def __init__(self, name):
self.name = name
my_dog = Dog("Spot")
print(my_dog.name)
# 输出: Spot
Python 如何在类实例中存储属性?
每个 Python 类实例都有一个命名空间。这是一个存放值的地方。命名空间是一个字典。你可以通过 __dict__ 查看它。当你请求 my_dog.name 时,Python 会在实例的命名空间中查找。如果在那里没有找到该名称,它会检查类。
Python 使用实例的命名空间来保存其值。
class Dog:
    kind = "canine"
my_dog = Dog()
my_dog.name = "Fido"
print(my_dog.name)
# 输出: Fido
print(my_dog.kind)
# 输出: canine
print(my_dog.__dict__)
# 输出: {'name': 'Fido'}
Python是如何为类实例查找方法的?
当你使用类似 my_dog.bark() 的方法时,Python会在类中查找该方法。如果这是一个用户定义的函数,Python会将其封装为一个方法,并将实例作为第一个参数添加。
当从实例调用时,Python会将类函数封装为方法。
class Dog:
    def bark(self):
        return "汪汪!"
d = Dog()
print(d.bark())
# 输出: 汪汪!
在 bark(self) 中,self 指的是 d。当你调用 d.bark() 时,Python 会将 d 作为第一个参数传递。
类实例可以像函数或列表一样工作吗?
可以。Python 类实例可以假装成许多东西。如果类中有一个名为 __call__ 的方法,那么你可以像调用函数一样调用该实例。如果类中有像 __getitem__ 这样的函数,它可以像列表或映射一样工作。
如果类定义了 call,Python 允许类实例像函数一样工作。
class Greeter:
    def __call__(self, name):
        return f"Hello, {name}!"
g = Greeter()
print(g("Ada"))
# 输出: Hello, Ada!
Python 类实例的历史时间线
Python 的类实例规则来自哪里?
Python 类实例源于面向对象设计。早期语言塑造了对象如何存储数据、运行代码以及像内置类型一样进行操作。Python 使这一切变得清晰、灵活且易于使用。
人们设计了使用对象类型的系统
1967 — Simula 类实例 Simula 引入了类实例作为具有自己数据的运行时对象。
1980 — Smalltalk 实例消息传递 Smalltalk 允许对象之间发送消息(方法调用)。
人们塑造了 Python 的模型
1991 — Python 0.9.0 添加类和实例 Python 支持基于类的设计,具有方法查找和实例存储。
2000 — Python 2.2 添加新式类 Python 允许所有类继承自 object,统一了方法处理和特殊方法。
人们扩展了实例的功能
2001 — 特殊方法改善实例行为 Python 2.2 支持丰富的比较、迭代和数值仿真。
2010 — 类装饰器和描述符 Python 3 使得控制实例设置和属性访问变得更加容易。
人们保持了 Python 实例的简单性和可预测性
2020 — 稳定的实例设计 Python 保持了实例处理的向后兼容性,使其简单且开放。
2025 — 最小变更 Python 保持实例规则不变,以保护可靠性。
Python 类实例的问题与解决方案
如何正确使用 Python 类实例?
Python 类实例帮助您创建存储数据和执行操作的对象。每个实例都有自己的值,并可以以特殊的方式进行操作。这些问题展示了 Python 类实例如何满足您代码中的实际需求。
问题:如何在 Python 中为不同的对象存储不同的值?
您正在制作一个游戏。每个玩家都有一个名字和一个分数。您希望每个玩家都能保留自己的值。
问题: 您需要一种方法来创建许多共享相同结构但保存不同数据的对象。
解决方案: 使用类来定义结构,然后为每个玩家创建一个新实例。
Python 允许您在每个实例中存储值。
class Player:
    def __init__(self, name, score):
        self.name = name
        self.score = score
p1 = Player("Ada", 10)
p2 = Player("Bob", 20)
print(p1.name, p1.score)
# prints: Ada 10
print(p2.name, p2.score)
# 输出: Bob 20
每个对象都有自己的名称和分数。这个类使之成为可能。
问题:如何在Python中对存储的数据执行操作?
你有一个计数器,用于跟踪用户点击的次数。你希望能够轻松地将总数加一。
问题:您需要一种存储数据并对其执行操作的方法。
解决方案:将数据放入实例中,并编写一个方法来更改它。
Python允许您添加方法以更改实例数据。
class Counter:
    def __init__(self):
        self.count = 0
    def click(self):
        self.count += 1
c = Counter()
c.click()
c.click()
print(c.count)
# 输出: 2
该方法使用 self 来改变对象的值。每个实例保持自己的计数。
问题:如何在Python中跨多个对象共享行为?
你在一个绘图工具中有许多形状。每个形状都有一个颜色。你希望所有形状都支持 paint() 操作。
问题:你需要给许多对象相同的方法,而不重复代码。
解决方案:使用一个类来定义该方法,然后创建共享该方法的实例。
Python允许你在类中定义共享方法。
class Shape:
    def paint(self, color):
        self.color = color
s1 = Shape()
s2 = Shape()
s1.paint("blue")
s2.paint("red")
print(s1.color)
# 输出: blue
print(s2.color)
# 输出: red
每个实例运行相同的方法,但存储自己的值。
问题:如何让对象在Python中表现得像内置类型?
您希望一个自定义对象,它的行为像列表,但能够跟踪每次访问。
问题:您希望您的类实例能够像列表一样响应 []。
解决方案:定义 __getitem__ 和 __setitem__ 来处理索引的使用。
Python允许类实例通过特殊方法表现得像列表。
class SpyList:
    def __init__(self):
        self.data = []
    def __getitem__(self, i):
        print(f"Getting item {i}")
        return self.data[i]
    def __setitem__(self, i, value):
print(f"设置项目 {i} 为 {value}")
self.data[i] = value
s = SpyList()
s.data.append("a")
s[0] = "b"
print(s[0])
# 输出:
# 设置项目 0 为 b
# 获取项目 0
# b
这个实例看起来像一个列表,但增加了新的行为。
问题:如何在Python中跟踪对象状态随时间的变化?
你想创建一个可以在调用时运行的对象,就像一个小工具。
问题:你需要一个可以接受参数并返回结果的对象,就像一个函数一样。
解决方案:在你的类中添加一个 __call__ 方法。
Python允许类实例像函数一样工作。
class Adder:
def __init__(self, base):
    self.base = base
def __call__(self, x):
    return self.base + x
add5 = Adder(5)
print(add5(3))
# 输出: 8
该对象像函数一样运行,因为它定义了 __call__。

