卡码笔记-最强八股文
首页
计算机基础
Python
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
大模型Github (opens new window)
代码随想录 (opens new window)
首页
计算机基础
Python
C++
Java
Go
🔥大模型🔥
  • 大模型面经
  • Java面经
  • C++面经
大模型Github (opens new window)
代码随想录 (opens new window)
  • 本栏必读

    • Python面试题专栏介绍
    • Python学习路线
    • Python零基础入门课
  • 基础语法

  • 函数、作用域与模块

  • 面向对象

    • Python中的类和对象是什么?
    • 实例属性和类属性有什么区别?
      • 简要回答
      • 详细回答
      • 知识拓展
    • 实例方法、类方法和静态方法有什么区别?
    • __new__和__init__有什么区别?
    • Python如何实现封装、继承和多态?
    • Python多继承的MRO是什么?super()如何工作?
    • Python常见魔术方法有哪些?
  • 进阶语法与语言机制

# 实例属性和类属性有什么区别?

面试官问:"Python实例属性和类属性有什么区别?"

很多人会说"一个属于对象,一个属于类",但没说清楚存储位置和修改影响。真正要讲清楚的是:实例属性存在对象的__dict__里,每个对象独立;类属性存在类的__dict__里,所有对象共享。 访问时实例属性优先,但修改时不会影响类属性。

# 简要回答

实例属性是对象自己的属性,每个对象独立拥有。 通常在__init__方法里通过self.attr = value创建,存储在对象的__dict__里。修改一个对象的实例属性不会影响其他对象。

类属性是类本身的属性,所有实例共享。 定义在类体里、方法外面,存储在类的__dict__里。修改类属性会影响所有没有同名实例属性的对象。

访问属性时,Python先查对象的__dict__(实例属性),再查类的__dict__(类属性)。 所以同名时实例属性优先。但通过self.attr = value赋值时,只会在对象的__dict__里创建或修改实例属性,不会修改类属性。

# 详细回答

# 定义和存储位置

class Dog:
    species = "Canis familiaris"  # 类属性,定义在类体
    
    def __init__(self, name, age):
        self.name = name      # 实例属性,通过self创建
        self.age = age        # 实例属性

dog1 = Dog("Buddy", 3)
dog2 = Dog("Max", 5)

print(dog1.__dict__)  # {'name': 'Buddy', 'age': 3}
print(dog2.__dict__)  # {'name': 'Max', 'age': 5}
print(Dog.__dict__['species'])  # Canis familiaris
1
2
3
4
5
6
7
8
9
10
11
12
13

name和age是实例属性,每个对象的__dict__里都有一份;species是类属性,只在Dog.__dict__里有一份。

# 访问优先级

读取属性时,实例属性优先:

class Counter:
    count = 0  # 类属性
    
    def __init__(self):
        self.count = 10  # 实例属性,同名

c = Counter()
print(c.count)        # 10,找到实例属性
print(Counter.count)  # 0,类属性没变
1
2
3
4
5
6
7
8
9

访问c.count时,Python先查c.__dict__,找到了实例属性count=10,就不再往上查类属性。

# 修改影响范围

修改实例属性只影响这个对象:

class Dog:
    species = "Canis"

dog1 = Dog()
dog2 = Dog()

dog1.species = "Felis"  # 给dog1创建了实例属性
print(dog1.species)     # Felis
print(dog2.species)     # Canis,dog2仍然读到类属性
print(Dog.species)      # Canis,类属性没变
1
2
3
4
5
6
7
8
9
10

dog1.species = "Felis"在dog1.__dict__里创建了实例属性,所以dog1.species现在读到的是实例属性。dog2和Dog.species都没受影响。

修改类属性会影响所有没有同名实例属性的对象:

class Dog:
    species = "Canis"

dog1 = Dog()
dog2 = Dog()

Dog.species = "Canis familiaris"  # 修改类属性
print(dog1.species)  # Canis familiaris
print(dog2.species)  # Canis familiaris

dog1.species = "Mixed"  # 给dog1创建实例属性
Dog.species = "Updated"  # 再次修改类属性
print(dog1.species)  # Mixed,不受影响
print(dog2.species)  # Updated,仍然读类属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14

实例属性与类属性的查找和修改

# 可变对象做类属性的坑

类属性如果是列表或字典等可变对象,所有实例会共享它,容易踩坑:

class Team:
    members = []  # 类属性,可变对象
    
    def __init__(self, name):
        self.name = name
    
    def add_member(self, member):
        self.members.append(member)

team1 = Team("Alpha")
team2 = Team("Beta")

team1.add_member("Alice")
team2.add_member("Bob")

print(team1.members)  # ['Alice', 'Bob'],不符合预期!
print(team2.members)  # ['Alice', 'Bob'],两个队伍共享一个列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

members是类属性,team1和team2的add_member都在修改同一个列表。正确做法是把可变对象放到实例属性里:

class Team:
    def __init__(self, name):
        self.name = name
        self.members = []  # 实例属性,每个对象独立

team1 = Team("Alpha")
team2 = Team("Beta")

team1.members.append("Alice")
team2.members.append("Bob")

print(team1.members)  # ['Alice']
print(team2.members)  # ['Bob']
1
2
3
4
5
6
7
8
9
10
11
12
13

# 什么时候用类属性

类属性适合存储所有对象共享的配置或常量:

class Circle:
    PI = 3.14159  # 所有圆共享的常量
    count = 0     # 统计创建了多少个圆
    
    def __init__(self, radius):
        self.radius = radius
        Circle.count += 1  # 每创建一个对象,计数器加1
    
    def area(self):
        return Circle.PI * self.radius ** 2

c1 = Circle(5)
c2 = Circle(10)
print(Circle.count)  # 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14

类属性也可以当作全局配置、版本号、默认值。如果需要跨所有对象统计或共享,用类属性;如果每个对象独立,用实例属性。

# 知识拓展

Q1:通过self能修改类属性吗?

不能直接修改,但能遮盖。self.attr = value只会在对象的__dict__里创建或修改实例属性。如果要修改类属性,必须通过类名:

class Test:
    value = 10

t = Test()
t.value = 20       # 创建实例属性
print(t.value)     # 20
print(Test.value)  # 10,类属性没变

Test.value = 30    # 修改类属性
print(Test.value)  # 30
1
2
3
4
5
6
7
8
9
10

Q2:删除实例属性后会怎样?

会继续读到类属性:

class Test:
    value = "class"

t = Test()
t.value = "instance"
print(t.value)  # instance

del t.value
print(t.value)  # class,现在读到类属性
1
2
3
4
5
6
7
8
9

Q3:类属性能是方法吗?

方法本质上也是类属性,只是值是一个函数对象。访问obj.method时,Python返回一个绑定方法对象,把obj绑定到self上。

Q4:能用__slots__限制实例属性吗?

可以。定义__slots__后,对象不再有__dict__,只能有__slots__里列出的属性。这能节省内存,但失去了动态添加属性的灵活性:

class Limited:
    __slots__ = ['x', 'y']

obj = Limited()
obj.x = 10  # 可以
obj.z = 20  # AttributeError: 'Limited' object has no attribute 'z'
1
2
3
4
5
6

Q5:如果类属性是不可变对象,修改它会怎样?

不可变对象(数字、字符串、元组)的"修改"实际是创建新对象并重新绑定名字。通过self.attr += 1会在对象的__dict__里创建实例属性:

class Test:
    count = 0

t = Test()
t.count += 1  # 等价于 t.count = t.count + 1
print(t.count)     # 1
print(Test.count)  # 0,类属性没变
1
2
3
4
5
6
7

上一篇:Python类和对象:类是蓝图,对象是实例
下一篇:实例方法、类方法和静态方法有什么区别?

Last Updated: 10/13/2026, 5:57:00 PM

← Python中的类和对象是什么? 实例方法、类方法和静态方法有什么区别? →

评论

验证登录状态...

侧边栏 侧边栏
夜间模式 夜间
卡码简历 卡码简历
代码随想录 代码随想录
卡码投递表 卡码投递表🔥
2026实习校招群 2026群
添加客服微信 2026实习校招客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记 支持卡码笔记
鼓励/支持/赞赏Carl 卡码笔记赞赏码
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪