目录
一、类和对象

1 类Class
- 什么是“类”?
- 定义:类是对一类事物(具有相同属性和行为的实体)的抽象描述,它定义了这类事物共同拥有的属性(数据)和方法(操作数据的行为)。
- 可以理解为:类是一个 “模板”,规定了某类对象 “是什么” 和 “能做什么”,但它本身并不占用内存空间,也不能直接被使用。
- 示例:
- “汽车” 可以视为一个类,它的属性包括颜色、品牌、排量等,方法包括启动、加速、刹车等。
- “学生” 可以视为一个类,属性包括姓名、年龄、学号等,方法包括上课、考试、交作业等。
- 如何创建类
- 数据成员:表明事物的特征。 相当于变量
- 方法成员:表明事物的功能。 相当于函数
- 通过
class关键字定义类。
类的创建语句语法:
class 类名 (继承列表):
实例属性(类内的变量) 定义
实例方法(类内的函数method) 定义
类变量(class variable) 定义
类方法(@classmethod) 定义
静态方法(@staticmethod) 定义
参考代码:
class Car:
def __init__(self, brand, color, price):
# 初始化属性:类内部的全局变量,在类内部任何实例化对象方法里面都可以使用
self.brand = brand # 实例属性
self.color = color
self.price = price
def __str__(self):
return f'这是一辆{self.brand},颜色是{self.color},价格为{self.price}'
def drive(self, speed): # 实例方法
return f'{self.brand}的最高速度可达{speed}km/h'
# 创建对象
car1 = Car('沃尔沃XC90', 'black', '700000')
# 调用对象的方法
print(car1.drive(500)) # 输出:沃尔沃XC90的最高速度可达500km/h
2 对象Object
- 什么是“对象”
- 定义:对象是类的具体实例,是根据类的模板创建出来的具体实体。它拥有类中定义的属性和方法,并且每个对象的属性可以有不同的具体值,同时会占用实际的内存空间。
- 类与对象的关系:类是抽象概念,对象是类的具体实例(如 “人类” 是类,“张三” 是对象)
- 示例:
- 根据 “汽车” 类创建的具体对象:一辆 “红色、特斯拉品牌、2.0T 排量” 的汽车,它可以执行 “启动”“加速” 等操作。
- 根据 “学生” 类创建的具体对象:“姓名为张三、年龄 18、学号 2023001” 的学生,他可以执行 “上课”“考试” 等操作。
- 如何创建对象
-
变量存储的是实例化后的对象地址
-
类参数按照初始化方法的形参传递:
- 对象是类的实例,具有类定义的属性和方法。
- 通过调用类的构造函数来创建对象。
- 每个对象有自己的状态,但共享方法。
对象的创建语句语法:
# 1. 先定义类
class 类名:
def __init__(self, 参数1, 参数2, ...): # 初始化方法(构造函数)
self.属性1 = 参数1 # 绑定实例属性
self.属性2 = 参数2# 2. 创建对象(实例化)
对象名 = 类名(参数1, 参数2, ...) # 传入__init__方法所需的参数
参考代码:
class Dog:
def __init__(self, name, age, color, breed):
self.name = name
self.age = age
self.color = color
self.breed = breed
def speak(self, language):
return '叫%s的狗可以听懂%s' % (self.name, language)
def eat(self, food):
return '叫%s的%s狗在吃%s' % (self.color, self.breed, food)
# 创建对象(实例化)
dog1 = Dog('小七', 12, 'yellow', '金毛') # 调用__init__,传入4个参数
dog2 = Dog('黄猪皮', 10, 'amber', '中华田园犬')
# 调用对象的方法
print(dog1.speak('Chinese')) # 输出:叫小七的狗可以听懂Chinese
print(dog2.eat('奶酪')) # 输出:叫amber的中华田园犬狗在吃奶酪
二、属性和方法
1 属性
1.1 实例属性
- 实例属性是属于类的每个对象(实例)的变量,用于存储对象的特定状态。
- 每个实例的属性值相互独立,修改一个实例的属性不会影响其他实例。
实例属性的使用语法
实例.属性名
实例属性使用:实例属性通常在 __init__ 方法中通过 self.属性名 = 值 的方式定义和初始化
class Person:
def __init__(self, name, age):
self.name = name # 实例属性:姓名
self.age = age # 实例属性:年龄
# 创建两个不同的实例
p1 = Person("小桃儿", 21)
p2 = Person("哞哞耶耶", 25)
print(p1.name) # 输出:小桃儿
print(p2.age) # 输出:25
1.2 类属性
- 类属性是属于类本身的变量,由该类的所有实例共享。
- 类属性存储的是与类相关的公共数据,不依赖于具体实例。
类属性的使用方法:
类名.属性名 或 实例名.属性名
类属性的使用:类属性直接在类的主体中定义(不在任何方法内)
class Circle:
PI = 3.14 # 类属性:圆周率(所有圆共享)
def __init__(self, radius):
self.radius = radius # 实例属性:每个圆的半径不同
# 通过类名访问
print(Circle.PI) # 输出:3.14
# 通过实例访问
c1 = Circle(5)
c2 = Circle(10)
print(c1.PI) # 输出:3.14
print(c2.PI) # 输出:3.14
- 通过类名修改:所有实例的类属性值会同步更新。
- 通过实例修改:实际上会为该实例创建一个同名的实例属性,屏蔽类属性,但不会影响其他实例。
class Myclass:
class_attr = 0
def __init__(self, subject, class_num, name):
self.subject = subject
self.class_num = class_num
self.name = name
def student(self):
# 当实例中没有同名属性时,会读取类属性,但是在复制时会创建实例属性(仅属于当前实例,不影响类属性)
self.class_attr += 1 # 结果为1,仅限当前实例
# 直接操作类属性(属于整个类,所有实例共享)
Myclass.class_attr += 1 # 结果为1,所有实例共享
return f'{self.name}在{self.class_num}学习{self.subject}'
p1 = Myclass('物理', '高二(3)班', '小桃儿')
print(p1.student())
print(p1.class_attr) # 输出为1
print(Myclass.class_attr) # 输出为1
1.3 实例属性与类属性区别
| 特征 | 实例属性 | 类属性 |
|---|---|---|
| 定义位置 | 在 __init__ 或实例方法中定义 | 直接在类中定义(不在任何方法内) |
| 绑定对象 | 每个实例独立拥有 | 所有实例共享同一个值 |
| 访问方式 | 实例名.属性名 | 类名.属性名 或 实例名.属性名 |
| 修改影响 | 只影响当前实例 | 修改会影响所有实例 |
| 内存占用 | 每个实例单独存储 | 所有实例共享同一块内存 |
2 方法
2.1 实例方法
- 实例方法是类中最常见的方法类型,用于操作对象的实例属性和实现对象的行为。
- 每个实例方法都与具体的对象实例绑定,通过
self参数访问实例的状态。
基本语法:实例方法的第一个参数必须是 self(约定俗成的名称,也可使用其他名称,但不建议)
class 类名(继承列表):
def 实例方法名(self, 参数1, 参数2, ...):
语句块
调用:
实例.实例方法名(调用传参)
# 或
类名.实例方法名(实例, 调用传参)
实例:(操作实例状态)
class Dog:
def __init__(self, name, age, color, breed):
self.name = name
self.age = age
self.color = color
self.breed = breed
# 实例方法
def speak(self, language):
return '叫%s的狗可以听懂%s' % (self.name, language)
# 实例方法
def eat(self, food):
return '叫%s的%s狗在吃%s' % (self.color, self.breed, food)
dog1 = Dog('小七', 12, 'yellow', '金毛')
# 实例.实例方法名(调用传参)
print(dog1.speak('Chinese')) # 叫小七的狗可以听懂Chinese
dog2 = Dog('黄猪皮', 10, 'amber', '中华田园犬')
# 类名.实例方法名(实例, 调用传参)
print(Dog.eat(dog2,'奶酪')) # 叫amber的中华田园犬狗在吃奶酪
2.2 类方法
- 类方法是绑定到类而非实例的方法。
- 它通过
@classmethod装饰器定义,第一个参数为cls(表示类本身),主要用于操作类属性或创建工厂方法。 - 类和该类的实例都可以调用类方法
- 类方法不能访问此类创建的对象的实例属性
基本用法:
class MyClass:
class_attr = 100 # 类属性
@classmethod
def class_method(cls, param):
# 类方法:第一个参数是类本身(cls
cls.class_attr = param # 修改类属性
return cls.class_attr
# 调用类方法(两种方式)
MyClass.class_method(200) # 方式1:通过类名直接调用
obj = MyClass()
obj.class_method(300) # 方式2:通过实例调用(不推荐)
类方法与实例方法的区别:
| 特性 | 类方法(@classmethod) | 实例方法 |
|---|---|---|
| 第一个参数 | cls(指向类) | self(指向实例) |
| 绑定对象 | 类 | 实例 |
| 访问权限 | 只能访问 / 修改类属性 | 可访问 / 修改实例属性和类属性 |
| 调用方式 | 类名.方法() 或 实例.方法() | 只能 实例.方法() |
| 典型场景 | 工厂方法、操作类属性 | 操作实例状态 |
类方法实例1:(工厂方法)
from datetime import datetime
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_dict(cls, data):
name, birthday_str = data.split(', ')
birthday = datetime.strptime(birthday_str, '%Y-%m-%d')
today = datetime.today()
age = today.year - birthday.year
# 检查是否已经过了生日
if (today.month, today.day) < (birthday.month, birthday.day):
age -= 1
return cls(name, age)
p1 = Person.from_dict('小桃, 2004-04-02')
print(p1.age) # 21
类方法实例2:(操作类属性)
class Myclass:
class_attr = 0
def __init__(self, subject, class_num, name):
self.subject = subject
self.class_num = class_num
self.name = name
def student(self):
# 当实例中没有同名属性时,会读取类属性,但是在复制时会创建实例属性(仅属于当前实例,不影响类属性)
self.class_attr += 1 # 仅限当前实例
# 直接操作类属性(属于整个类,所有实例共享)
Myclass.class_attr += 1 # 所有实例共享
return f'{self.name}在{self.class_num}学习{self.subject}'
@classmethod
def class_method(cls):
# dict是可以进行Key的新增,object也是
# 不是在修改实例对象的属性,而是给一个对象Myclass追加一个属性
cls.class_num = 0 # 等同于Myclass.class_num
cls.class_attr += 1
return cls.class_attr # 类方法
p1 = Myclass('物理', '高二(3)班', '小桃儿')
# 实例方法调用,self.class_attr+=1,Myclass.class_attr+=1
print(p1.student()) # 小桃儿在高二(3)班学习物理
print(p1.class_attr) # 1(self.class_attr+=1)
print(p1.class_method()) # 2(Myclass.class_attr+=1,cls.class_attr += 1)
print(Myclass.class_method()) # 3(Myclass.class_attr+=1,cls.class_attr += 1,cls.class_attr += 1)
print(Myclass.class_num) # 0(cls.class_num = 0)(类属性)
print(p1.class_num) # 高二(3)班(实例属性)
2.3 静态方法
- 静态方法是属于类但不与类或实例绑定的方法。
- 它通过
@staticmethod装饰器定义,不强制要求传递self或cls参数,主要用于封装与类相关的工具函数。
基本用法:
class Calculator:
@staticmethod
def add(a, b):
# 静态方法:不依赖类或实例的状态
return a + b
@staticmethod
def multiply(a, b):
return a * b
# 调用静态方法(两种方式)
result1 = Calculator.add(3, 4) # 方式1:通过类名调用(推荐)
obj = Calculator()
result2 = obj.multiply(5, 6) # 方式2:通过实例调用(不推荐)
print(result1) # 输出:7
print(result2) # 输出:30
静态用法、实例方法、类方法区别:
| 特性 | 静态方法(@staticmethod) | 实例方法 | 类方法(@classmethod) |
|---|---|---|---|
| 第一个参数 | 无强制要求参数 | self(指向实例) | cls(指向类) |
| 绑定对象 | 类 | 实例 | 类 |
| 访问权限 | 无法直接访问类或实例属性 | 可访问实例和类属性 | 可访问类属性 |
| 调用方式 | 类名.方法() 或 实例.方法() | 实例.方法() | 类名.方法() 或 实例.方法() |
| 典型场景 | 工具函数、与类相关的逻辑 | 操作实例状态 | 工厂方法、操作类属性 |
静态方法实例1:(工具函数封装)
# 静态方法:不可访问类或实例属性
# 常用于封装与类相关的工具逻辑:比如验证输入
class Math:
@staticmethod
def sqrt(num):
return num ** 0.5
@staticmethod
def exp2(x):
return 2 ** x
# 静态方法:可以通过类或实例调用
print(Math.sqrt(4)) # 2.0
print(Math.exp2(4)) # 16
obj = Math()
print(obj.sqrt(16)) # 4.0
2.4 魔术方法
- 魔术方法是一类特殊的方法,以双下划线(
__)开头和结尾,如__init__、__str__。 - 它们由 Python 解释器自动调用,用于实现对象的内置行为(如初始化、运算、迭代等)。
- 掌握魔术方法能让你的类具备更强大的交互能力,使代码更 Pythonic。
常用方法:
__init__(self, ...): 初始化对象,通常用于设置对象的属性。
__str__(self): 定义对象的字符串表示形式,可通过str(object)或print(object)调用。例如,您可以返回一个字符串,描述对象的属性。
__repr__(self): 定义对象的“官方”字符串表示形式,通常用于调试。可通过repr(object)调用。
__len__(self): 定义对象的长度,可通过len(object)调用。通常在自定义容器类中使用。
__getitem__(self, key): 定义对象的索引操作,使对象可被像列表或字典一样索引。例如,object[key]。
__setitem__(self, key, value): 定义对象的赋值操作,使对象可像列表或字典一样赋值。例如,object[key] = value。
__delitem__(self, key): 定义对象的删除操作,使对象可像列表或字典一样删除元素。例如,del object[key]。
__iter__(self): 定义迭代器,使对象可迭代,可用于for循环。
__next__(self): 定义迭代器的下一个元素,通常与__iter__一起使用。
__add__(self, other): 定义对象相加的行为,使对象可以使用+运算符相加。例如,object1 + object2。
__sub__(self, other): 定义对象相减的行为,使对象可以使用-运算符相减。
__eq__(self, other): 定义对象相等性的行为,使对象可以使用==运算符比较。
__lt__(self, other): 定义对象小于其他对象的行为,使对象可以使用<运算符比较。
__gt__(self, other): 定义对象大于其他对象的行为,使对象可以使用>运算符比较。
__call__(self, other)是一个特殊的方法(也称为“魔法方法”),它允许一个对象像函数一样被调用。
实例:
class MyNumber:
# init是自动调用:完成实例化对象属性的初始化,不需要返回值
# self.num的num是字面量,=后面的num是变量
def __init__(self, num):
self.num = num
self.len = len(self.num)
self.name = '小桃儿'
# 定义对象相加的行为,使对象可以使用 + 运算符相加
# self指向第一个对象,other指向其他对象
def __add__(self, other):
return self.num + other.num
# 相乘
def __mul__(self, other):
return self.num * other.num
# 判断是否相等
def __eq__(self, other):
return self.num == other.num
# 定义对象的字符串表示形式,可通过`str(object)`或`print(object)`调用。
# map() 函数将 str 函数应用于 self.num 中的每个元素,将所有元素转换为字符串
# join() 方法将可迭代对象(如列表)中的字符串用指定分隔符 ', ' 连接成一个字符串。
def __str__(self):
return f'[{', '.join(map(str, self.num))}]'
# 定义对象的长度
def __len__(self):
return len(self.num)
# 定义索引删除del obj[key]
def __delitem__(self, index):
del self.num[index]
# 定义索引赋值obj[key] = value,相当于修改
def __setitem__(self, index, value):
self.num[index] = value
# 定义索引访问
def __getitem__(self, index):
return self.num[index]
num3 = MyNumber([1, 2, 6])
print(num3) # [1, 2, 6] 返回字符串(__str__)
print(num3.len) # 3 长度(__len__)
print(num3[2]) # 6 索引访问 (__getitem__)
print(num3.name) # 小桃儿 调用实例属性
num3[1] = 4 # 索引赋值obj[key] = value,相当于修改(__setitem__)
print(num3) # [1, 4, 6]
del num3[1] # 索引删除del obj[key] (__delitem__)
print(num3) # [1, 6]
三、综合使用
电商产品类设计:
class Product:
# 类属性
discount_rate = 0.9 # 默认折扣为9折
product_count = 0 # 产品计数器
def __init__(self, name, price, stock):
self.name = name
self.price = price
self.stock = stock
Product.product_count += 1 # 每次创建产品递增计数器
def discount_price(self):
return self.price * Product.discount_rate
# 更新库存,当卖出去物品后
def update_stock(self, sold_quantity):
if sold_quantity > self.stock:
raise ValueError("库存不足")
self.stock -= sold_quantity
return self.stock
@classmethod
def set_discount_rate(cls, rate):
# 类方法:修改全局折扣率
if 0 < rate <= 1:
cls.discount_rate = rate
else:
raise ValueError("折扣率必须在0-1之间")
@classmethod
def get_product_count(cls):
# 类方法:获取产品种类总数
return cls.product_count
@staticmethod
def price_valid(price):
# 静态方法:验证价格是否正确
return isinstance(price, (int,float)) and price > 0
# 创建实例对象验证
p1 = Product("手机", 5000, 100)
p2 = Product("耳机", 300, 200)
# 使用实例方法
print(p1.discount_price()) # 4500.0
print(p2.update_stock(20)) # 180
# 使用类方法
Product.set_discount_rate(0.8)
print(p1.discount_price()) # 4000.0
print(Product.get_product_count()) # 2
# 使用静态方法
print(Product.price_valid(-199)) # False
注意!!
今日注意就是全部内容都要注意!!!
2万+

被折叠的 条评论
为什么被折叠?



