Appearance
类与对象
函数把一段逻辑收起来,类把一组数据和操作这些数据的函数收在一起。比如"文章"有标题、作者、内容这些数据,还有发布、撤回、统计字数这些操作——用类把它们打包成一个整体,比散在变量和函数里更清晰。
类是模板,对象是根据模板造出来的实例。Article 是类,article1 article2 是两个具体的对象。
一、定义类
python
class Article:
"""文章类。"""
def __init__(self, title, author):
"""初始化方法,创建对象时自动调用。"""
self.title = title # 实例属性
self.author = author
self.status = "草稿" # 默认值
def publish(self):
"""发布文章。"""
if self.status == "草稿":
self.status = "已发布"
print(f"{self.title} 已发布")
else:
print(f"{self.title} 已经是 {self.status},无法重复发布")
def withdraw(self):
"""撤回文章。"""
if self.status == "已发布":
self.status = "草稿"
print(f"{self.title} 已撤回")
else:
print(f"{self.title} 当前状态是 {self.status},无法撤回")class Article: 定义一个类,名字用驼峰命名(每个单词首字母大写)。__init__ 是初始化方法,创建对象时自动调用——self.title = title 把传入的 title 存到对象的属性里。
self 是对象自己。self.title 是这个对象自己的 title 属性,self.publish() 是调用这个对象自己的 publish 方法。这个概念一开始容易绕:self 不是 Python 关键字,是约定俗成的参数名,表示"当前对象"。
二、创建对象
python
article1 = Article("Python 入门", "张三")
article2 = Article("Go 并发", "李四")
print(article1.title) # Python 入门
print(article2.status) # 草稿
article1.publish() # Python 入门 已发布
article1.publish() # Python 入门 已经是 已发布,无法重复发布
article2.withdraw() # Go 并发 当前状态是 草稿,无法撤回Article("Python 入门", "张三") 创建一个对象,__init__ 被调用,title 和 author 存进对象。article1.publish() 调用这个对象的 publish 方法,方法里 self.status 就是 article1 自己的 status 属性。
每个对象有自己的一套属性——article1.status 和 article2.status 互不影响,改一个不会影响另一个。
三、属性
属性就是存在对象上的变量。实例属性是每个对象各自独立的一份:
python
class Contact:
def __init__(self, name, phone):
self.name = name
self.phone = phone
c1 = Contact("张三", "13800138000")
c2 = Contact("李四", "13900139000")
print(c1.name) # 张三
print(c2.name) # 李四c1.name 和 c2.name 是两个不同的值,各改各的。
还有一类类属性——所有对象共享,定义在类里、方法外:
python
class Contact:
# 类属性
default_country = "中国"
def __init__(self, name, phone):
self.name = name
self.phone = phone
c1 = Contact("张三", "13800138000")
c2 = Contact("李四", "13900139000")
print(c1.default_country) # 中国
print(c2.default_country) # 中国
# 改类属性会影响所有对象
Contact.default_country = "美国"
print(c1.default_country) # 美国
print(c2.default_country) # 美国类属性用得不多,但要知道有这个概念——大部分数据还是放实例属性,因为每个对象自己管自己的数据更清晰。
四、方法
定义在类里的函数叫方法。实例方法第一个参数是 self,能访问对象的属性和其他方法:
python
class Article:
def __init__(self, title, author, content=""):
self.title = title
self.author = author
self.content = content
self.status = "草稿"
def word_count(self):
"""统计文章字数。"""
return len(self.content)
def preview(self, max_length=50):
"""生成文章预览。"""
if len(self.content) <= max_length:
return self.content
return self.content[:max_length] + "..."
article = Article("Python 入门", "张三", "Python 是一门很好学的编程语言...")
print(article.word_count()) # 14
print(article.preview(10)) # Python 是一门很...word_count 和 preview 都是实例方法,第一个参数是 self,调用时不用传——article.word_count() 自动把 article 作为 self 传进去。
还有一种类方法,用 @classmethod 装饰,第一个参数是 cls(类本身):
python
class Article:
# 类属性
article_count = 0
def __init__(self, title, author):
self.title = title
self.author = author
self.status = "草稿"
Article.article_count += 1 # 每创建一个对象,计数加 1
@classmethod
def get_count(cls):
"""返回已创建的文章总数。"""
return cls.article_count
a1 = Article("Python 入门", "张三")
a2 = Article("Go 并发", "李四")
print(Article.get_count()) # 2类方法用得少,主要用在"创建对象总数的统计""工厂方法"这类场景——日常写类,99% 都是实例方法。
五、私有属性
有些属性不希望外部直接访问或修改,可以用两个下划线开头:
python
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.__balance = balance # 私有属性
def deposit(self, amount):
"""存款。"""
if amount > 0:
self.__balance += amount
print(f"存入 {amount},余额 {self.__balance}")
def get_balance(self):
"""查询余额。"""
return self.__balance
account = BankAccount("张三", 1000)
account.deposit(500) # 存入 500,余额 1500
# 直接访问私有属性会报错
# print(account.__balance) # AttributeError
print(account.get_balance()) # 1500__balance 是私有属性,类外部无法直接访问 account.__balance,只能通过 deposit 和 get_balance 操作。
这个私有是"约定上的私有",不是真正的禁止访问——Python 里没有真正的私有属性,account._BankAccount__balance 还是能绕过去。但两个下划线是一个信号:告诉使用者"别直接碰这个属性,用我提供的方法来操作"。
六、组合
对象可以包含其他对象,这叫组合:
python
class Author:
def __init__(self, name, email):
self.name = name
self.email = email
class Article:
def __init__(self, title, author):
self.title = title
self.author = author # author 是一个 Author 对象
def show_author(self):
print(f"作者:{self.author.name}({self.author.email})")
author = Author("张三", "zhangsan@example.com")
article = Article("Python 入门", author)
article.show_author() # 作者:张三(zhangsan@example.com)Article 的 author 属性是一个 Author 对象。组合比继承更常用——"文章有作者"用组合,"作者是人"才用继承。
类什么时候用?当数据和方法有天然的一对多关系时。比如文章有标题、作者、内容、状态这些数据,还有发布、撤回、统计字数这些操作——数据和操作明显绑定在一起,用类就很自然。如果只是几个零散函数,不一定要硬套类。