Files
Cloud-book/Python/Python面向对象/类的成员.md
2025-08-27 17:10:05 +08:00

257 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 类的组成成员分类
Python 类的组成成员可以分为三大类:字段(变量)、​​​方法(函数)和​​​​属性(特殊方法),它们的定义方式、作用域和调用规则各有不同。
## 字段(变量)
字段分为​​实例变量​​和​​类变量​​,核心区别在于存储位置和作用对象:
- 实例变量:每个对象独立拥有一份实例变量,修改不影响其他对象。
- 类变量:通过类名或实例均可访问,但通过实例修改会创建同名实例变量,覆盖类变量。
**示例:**
```python
class Dog:
species = "Canis lupus" # 类变量
def __init__(self, name):
self.name = name # 实例变量
d = Dog("Buddy")
print(d.name)
d1 = Dog()
print(Dog.species)
d1.species = "Mutt"
print(Dog.species)
```
## 方法(函数)
方法分为实例方法​​、​​类方法​​和​静态方法​​,区别在于参数和调用方式:
- 实例方法:第一个参数为 self指向调用该方法的实例必须通过对象调用可访问实例变量和类变量。
- ​​类方法:使用 @classmethod 装饰器,参数为 cls指向类本身操作类变量或实现工厂模式创建实例
- ​静态方法:使用 @staticmethod 装饰器,无默认参数,不依赖类或实例状态;执行与类相关的工具函数。
**示例:**
```python
class Dog:
species = "Canis lupus" # 类变量
def __init__(self, name, age=0):
self.name = name # 实例变量
self.age = age
def bark(self):
print(f"{self.name} is barking!")
@classmethod
def create_from_string(cls, s):
name, age = s.split(",")
return cls(name, int(age)) # 创建实例时调用__init__方法
@classmethod
def get_species(cls):
return cls.species
@staticmethod
def describe():
return "Dogs are domesticated animals."
d = Dog("Buddy", 11)
d.bark() # Buddy is barking!
d1 = Dog.create_from_string("Max,5") # 通过类方法创建实例
d2 = Dog("Bella", 3) # 通过类方法创建实例
print(d2.name)
print(d1.age)
print(Dog.get_species()) # 类方法调用
d3 = Dog("Charlie", 2)
print(d3.get_species()) # 实例调用
print(Dog.describe()) # 静态方法调用
```
## 属性Property
属性是​​伪装成字段的方法​​,通过 @property 装饰器实现,用于封装逻辑。
```python
class BankAccount:
def __init__(self, balance):
self.__balance = balance
@property
def balance(self):
return self.__balance
@balance.setter
def balance(self, value):
if value >= 0:
self.__balance = value
@balance.deleter
def balance(self):
del self.__balance
account = BankAccount(100)
print(account.balance) # 调用getter方法
account.balance = 200 # 调用setter方法
del account.balance # 删除属性
print(account.balance)
```
## 其他特殊成员
- 魔术方法:如 `__init__`(构造函数)、`__str__`(字符串表示)等,用于自定义类的行为。
- 私有成员:通过双下划线前缀(如 __variable实现封装仅在类内部访问。
**示例**
```python
class MyClass:
def __init__(self, value):
self.value = value # 公有属性
self.__value = value # 私有属性
def public_method(self):
return f'这是类的公有方法, value: {self.value}'
def __private_method(self):
return f'这是类的私有方法, value: {self.__value}'
def get_value(self):
return self.__value # 通过公有方法访问私有属性
obj = MyClass(10)
print(obj.value) # 访问公有属性
print(obj.public_method()) # 调用公有方法
print(obj.__value) # 访问公有属性
print(obj.__private_method()) # 调用私有方法
```
# 案例
**需求**
- 设计一个 `Game`
- 属性:
- 定义一个类属性 `top_score` 记录游戏的历史最高分
- 定义一个实例属性 `player_name` 记录当前游戏的玩家姓名
- 方法:
- 静态方法 `show_help` 显示游戏帮助信息
- 类方法 `show_top_score` 显示历史最高分
- 实例方法 `start_game` 开始当前玩家的游戏
- 主程序步骤
1. 查看帮助信息
2. 查看历史最高分
3. 创建游戏对象,开始游戏
![img-方法综合案例](类的成员/方法综合案例.png)
```python
class Game(object):
# 游戏最高分,类属性
top_score = 0
@staticmethod
def show_help():
print("帮助信息:让僵尸走进房间")
@classmethod
def show_top_score(cls):
print("游戏最高分是 %d" % cls.top_score)
def __init__(self, player_name):
self.player_name = player_name
def start_game(self):
print("[%s] 开始游戏..." % self.player_name)
# 使用类名.修改历史最高分
Game.top_score = 999
# 1. 查看游戏帮助
Game.show_help()
# 2. 查看游戏最高分
Game.show_top_score()
# 3. 创建游戏对象,开始游戏
game = Game("小明")
game.start_game()
# 4. 游戏结束,查看游戏最高分
Game.show_top_score()
```
# 总结
| 特性 | 普通方法 | 类方法 | 静态方法 |
| :---------- | :------------------ | :---------------- | :-------------------- |
| 定义方式 | 不需要装饰器 | `@classmethod` | `@staticmethod` |
| 第一个参数 | `self` | `cls` | 无 |
| 访问权限 | 访问实例属性和方法 | 访问类属性和方法 | 无法访问类和实例属性 |
| 调用方式 | 通过实例调用 | 通过类或实例调用 | 通过类或实例调用 |
| 适用场景 | 实例相关操作 | 与类相关的操作 | 与类无关的操作 |
# isinstace 与 issubclass
isinstance(a,b)判断a是否是b类或者b类的派生类实例化的对象
```python
class A:
pass
class B(A):
pass
obj = B()
print(isinstance(obj,B))
print(isinstance(obj,A))
```
issubclass(a,b) 判断a类是否是b类或者b的派生类的派生类
```python
class A:
pass
class B(A):
pass
class C(B):
pass
print(issubclass(B,A))
print(issubclass(C,A))
```
思考:那么 list str tuple dict等这些类与 Iterble类 的关系是什么?
```python
from collections import Iterable
print(isinstance([1,2,3], list)) # True
print(isinstance([1,2,3], Iterable)) # True
print(issubclass(list, Iterable)) # True
# 由上面的例子可得这些可迭代对象list str tuple dict等 都是 Iterable 的子类。
```