8.属性
属性是对象所拥有的数据。Python中有两种主要的属性:实例属性和类属性。
8.1 类属性 (所有对象共享)
定义在类中(不通过 self),但在任何方法(这个方法指的就是类里的函数)之
外。它们被所有实例共享。可以通过类名或实例访问(但通过实例修改时,会创建一个同名的实例属性,从而“遮盖”类属性,并不影响类属性本身)。
存储位置:类的 __dict__ 属性中。
关键区别:修改类变量会影响所有实例(除非在实例中重新定义)。
语法:attribute = value(在类体中,不缩进在方法内)
| | | | |
|---|
| | | | species = "Canis" |
| | | | Dog.species |
| | | buddy.species | |
class Dog: species = "Canis familiaris" # 类属性(所有Dog实例共享) def __init__(self, name, age): self.name = name # 实例属性 self.age = age # 实例属性 创建对象:buddy = Dog("Buddy", 5)max = Dog("Max", 3)访问类属性(通过类名或实例):print(Dog.species) # 通过类访问,输出: Canis familiarisprint(buddy.species) #通过实例访问, 输出: Canis familiarisprint(max.species) # 输出: Canis familiaris修改类属性(影响所有实例):Dog.species = "Canis lupus"print(buddy.species) # 输出: Canis lupusprint(max.species) # 输出: Canis lupus
8.2 实例属性(每个对象独立)
定义在 __init__ 或其他实例方法中,通过 self.属性名 赋值。每个实例拥有独立的实例属性。
存储位置:每个对象的 __dict__ 属性中。
关键区别:修改一个对象的实例变量不会影响其他对象。
语法:self.attribute = value
| | | | |
|---|
| | __init__ | | self.name = name |
| | | | buddy.name |
| | | | buddy.name |
class Dog: def __init__(self, name, age): self.name = name # 实例属性 self.age = age # 实例属性创建2个独立对象:buddy = Dog("Buddy", 5)max = Dog("Max", 3)修改buddy的实例属性:buddy.name = "Buddy Jr." # 修改buddy的name验证独立性:print(buddy.name) # 输出: Buddy Jr.print(max.name) # 输出: Max (未受影响)
✅ 验证:
🧭实例变量(实例属性)的内存存储验证
print(buddy.__dict__) # 输出: {'name': 'Buddy Jr.', 'age': 5}print(max.__dict__) # 输出: {'name': 'Max', 'age': 3}
✅ 验证:每个对象的 __dict__ 显示独立的实例变量。
8.3 属性查找顺序
当访问 obj.attr 时,Python 按照以下顺序查找:
🌍示例:
class Employee: company = "ABC Inc." # 类属性 raise_amount = 1.05 def __init__(self, name, salary): self.name = name # 实例属性 self.salary = salary def apply_raise(self): # 访问类属性 self.salary = int(self.salary * Employee.raise_amount)①. 创建对象emp1 = Employee("John", 50000)emp2 = Employee("Jane", 60000)②. 类属性被所有实例共享print(emp1.company) # ABC Inc.print(emp2.company) # ABC Inc.③. 修改类属性Employee.company = "XYZ Ltd."print(emp1.company) # XYZ Ltd.print(emp2.company) # XYZ Ltd.④. 尝试通过实例修改类属性:实际是创建了实例属性emp1.company = "Individual"print(emp1.company) # Individual(实例属性)print(emp2.company) # XYZ Ltd.(仍是类属性)print(Employee.company) # XYZ Ltd.(类属性未变)⑤. 删除实例属性后,重新访问到类属性del emp1.companyprint(emp1.company) # XYZ Ltd.
注:如果通过实例修改类属性,实际上是为该实例创建了一个同名的实例属性,不会影响类属性本身
✅ 验证:
初始时,emp1.company和 emp2.company共享类属性company。
Employee.company ="XYZ Ltd." 后,所有实例更新。
emp1.company ="Individual"在emp1实例中创建了新实例属性,覆盖了类属性,但 emp2.company仍使用类属性。
🏁类变量(类属性)的内存存储验证
print(Employee.__dict__) # 输出:{'company': 'XYZ Ltd.'...}print(emp1.__dict__) # 输出:{'name': 'John', 'salary': 50000, 'company': 'Individual'}print(emp2.__dict__) # 输出:{'name': 'Jane', 'salary': 60000}
✅ 验证:
Employee.__dict__ 显示类属性 company
emp1.__dict__ 包含覆盖后的 company实例属性
emp2.__dict__ 无 company,因此访问 emp2.company时会回退到类属性
8.4实例变量(即实例属性)与类变量(即类属性)的区别 | | |
| 通常在__init__或其它实例方法中通过self创建 | |
| 属于具体实例,每个实例独立拥有,每个对象独立,修改不影响其他对象 | 所有对象共享,修改影响所有实例 |
| | 可通过类(cls.var)或实例(obj.var)访问 |
| | 通过类修改会影响所有实例;通过实例修改会创建同名的实例变量,遮盖类变量 |
| | |
| | |
| | |
错误常见点:在 __init__ 中写 company = "TechCorp"(应为 self.company)
🌐示例对比:
class Employee: # 类变量 company = "ABC Corp" employee_count = 0 def __init__(self, name): # 实例变量 self.name = name Employee.employee_count += 1 # 通过类名修改类变量e1 = Employee("Alice")e2 = Employee("Bob")print(e1.name) # Alice (实例变量)print(e2.name) # Bob (实例变量)print(Employee.company) # ABC Corp (通过类访问类变量)print(e1.company) # ABC Corp (通过实例访问类变量)# 尝试通过实例修改类变量e1.company = "XYZ Inc" # 创建实例变量,遮盖类变量print(e1.company) # XYZ Inc (实例变量)print(Employee.company) # ABC Corp (类变量未变)print(e2.company) # ABC Corp (仍为类变量)# 类变量可以被所有实例共享,如计数器print(Employee.employee_count) # 2