【Python篇】Python基础——08day.面向对象编程中类和对象的基本概念及属性和方法的常见分类和使用场景

目录

前言

一、类和对象

1.类→Class

1.1概念

1.2创建

2.对象→Object

2.1概念

2.2创建

二、属性和方法

1. 实例属性

2. 实例方法

3. 类属性

4. 类方法

5. 静态方法

5.1 综合应用

6. 构造方法

7. 初始化方法

8. 魔术方法

8.1 常用方法

8.2 案例参考

总结


前言

这章讲的面向对象编程(Object-Oriented Programming,简称OOP)是一种通过组织对象来设计程序的编程方法。为什么需要类和对象?对比面向过程编程(算账用算盘 vs 用Excel表格),说明OOP更贴合现实世界思维(万物皆对象),代码更易组织、复用和扩展。OOP的核心思想可归纳为四大特性:封装、继承、多态和抽象。


一、类和对象

1.类→Class

1.1概念

类是对一类对象的抽象,是对象的模板或蓝图。它定义了对象的属性(特征)和方法(功能)。

“类”就像“汽车设计图”定义了所有汽车都应该有轮子、发动机、方向盘(属性),都应该能跑、能刹车、能鸣笛(方法)。它本身不是一辆车,但所有的汽车都依据它来制造。

类就是提供了一种结构化的方式来描述复杂的事物或概念。

例如: 

【Python篇】Python基础——08day.面向对象编程中类和对象的基本概念及属性和方法的常见分类和使用场景_第1张图片

1.2创建

1、数据成员:表明事物的特征。  相当于变量

2、方法成员:表明事物的功能。  相当于函数

3、通过 class 关键字定义类。

4、类的创建语句语法:

class 类名 (继承列表):
	实例属性(类内的变量) 定义
    实例方法(类内的函数method) 定义
    类变量(class variable) 定义
    类方法(@classmethod) 定义
    静态方法(@staticmethod) 定义

创建一个Dog类

class Dog:  # 关键字class + 类名(通常大写开头,遵循驼峰命名)
    # 初始化方法(构造器)-- 后面详讲,这里先会用
    def __init__(self, name, breed):  # self代表未来创建的对象实例本身
        # 定义属性:self.属性名
        self.name = name    # 实例属性:狗狗的名字
        self.breed = breed  # 实例属性:狗狗的品种
        self.age = 0        # 实例属性:初始年龄为0

我们详细解释一下这个类:​​
class Dog:  声明一个名为Dog的类。
def __init__(self, ...): 一个特殊的方法(构造方法/初始化方法),当创建一个新的Dog对象时自动调用。
self: 这是最关键的,它代表正在被创建的具体的那个狗的对象​(实例)。通过self.name = name,我们给这只具体的狗设置了一个名为name的属性,其值为传入的参数name。
​核心:​​ __init__方法是在初始化具体对象时使用的,依据类给具体对象(self)赋予具体的属性值。

注意点

  • 类名就是标识符,建议首字母大写
  • 类名实质上就是变量,它绑定一个类
  • self代表类实例化的对象本身

2.对象→Object

2.1概念

人以群分,每个人就是一个对象。 对象是类的实例化,它是根据类的描述(蓝图)创建出来的一个实体,是类的实际数据存储,具有类所定义的属性和方法。

2.2创建

例如刚才类是“根据图纸造出来的车”​。根据“汽车设计图”(类),我制造了一辆车牌是云A·88888的黑色奔驰(对象1),然后又制造了一辆车牌是云A·7777777白色宝马(对象2)。它们都是汽车(类),但都是具体的、拥有各自属性的个体(对象)。

【Python篇】Python基础——08day.面向对象编程中类和对象的基本概念及属性和方法的常见分类和使用场景_第2张图片

构造函数调用表达式为:

变量 = 类名([参数])

1变量存储的是实例化后的对象地址 
2 类参数按照初始化方法的形参传递

  • 对象是类的实例,具有类定义的属性和方法。
  • 通过调用类的构造函数来创建对象。
  • 每个对象有自己的状态,但共享方法。 

我们以刚才的Dog类接着举例 

# 创建Dog类的对象 (实例化)
my_dog = Dog("旺财", "金毛")  # 调用类名(参数) 相当于自动调用__init__
your_dog = Dog("小黑", "泰迪")

# 访问对象的属性
print(my_dog.name)   # 输出: 旺财
print(your_dog.breed) # 输出: 泰迪

# 改变对象的属性
my_dog.age = 3       # 旺财3岁了
your_dog.age = 2     # 小黑2岁了
print(my_dog.age)    # 输出: 3

我们详细解释一下这个代码:

my_dog = Dog("旺财", "金毛"):这是实例化的关键一步

解释器会:

1、在内存中开辟一块空间存放一个新的Dog对象。

2、自动调用Dog.__init__(self, "旺财", "金毛")。
这里的self指的就是这块新开辟的内存空间(新对象)!解释器把self指向新对象,然后把"旺财"传给name参数,"金毛"传给breed参数。
在__init__方法内部,语句self.name = "旺财"就是在给这个新对象​(self)设置一个属性name,值是"旺财"。self.breed = "金毛"同理。
my_dog:是一个变量,它指向​(引用)了内存中那个代表“旺财”的对象。操作my_dog就是在操作旺财这只具体的狗。

        

二、属性和方法

有了类和对象,它们得‘有血有肉’(属性)还得‘能动能做’(方法)。属性就像对象的内在特征(身高、体重、颜色),方法就是对象能做什么(跑、跳)。

1. 实例属性

1、每个实例有自己的变量,称为实例变量(也叫属性)

2、属性的使用语法

实例.属性名
class Dog:
    def eat(self, food):
        print(self.color, '的', self.kinds, '正在吃', food)

# 创建一个实例:
dog1 = Dog()
dog1.kinds = "京巴"  # 添加属性
dog1.color = "白色"
dog1.color = "黄色"  # 修改属性
print(dog1.color, '的', dog1.kinds)

dog2 = Dog()
dog2.kinds = "藏獒"
dog2.color = "棕色"
print(dog2.color, '的', dog2.kinds)

实例方法和实例属性(实例变量)结合在一起用:

class Dog:
    def eat(self, food):
        print(self.color, '的', self.kinds, '正在吃', food)

# 创建第一个对象
dog1 = Dog()
dog1.kinds = '京巴'  # 添加属性kinds
dog1.color = '白色'  # 添加属性color
dog1.eat("骨头")

dog2 = Dog()
dog2.kinds = '牧羊犬'
dog2.color = '灰色'
dog2.eat('包子')

2. 实例方法

class 类名(继承列表):
    def 实例方法名(self, 参数1, 参数2, ...):
        "文档字符串"
        语句块
  • 实例方法就是函数,至少有一个指向实例对象的形参  self

调用:

实例.实例方法名(调用传参)
# 或
类名.实例方法名(实例, 调用传参)

带有实例方法的简单的Dog类

class Dog:
    """这是一个种小动物的定义
    这种动物是狗(犬)类,用于创建各种各样的小狗
    """

    def eat(self, food):
        """此方法用来描述小狗吃东西的行为"""
        print("小狗正在吃", food)

    def sleep(self, hour):
        print("小狗睡了", hour, "小时!")

    def play(self, obj):
        print("小狗正在玩", obj)


dog1 = Dog()
dog1.eat("骨头")
dog1.sleep(1)
dog1.play('球')

help(Dog)  # 可以看到Dog类的文档信息


3. 类属性

类属性是类的属性,此属性属于类,不属于此类的实例

作用:通常用来存储该类创建的对象的共有属性
类属性说明:
        类属性,可以通过该类直接访问
        类属性,可以通过类的实例直接访问


类属性示例:

class Human:
    total_count = 0  # 创建类属性  self.name = name
    def __init__(self, name):
        self.name = name

print(Human.total_count)
h1 = Human("小张")
print(h1.total_count)


4. 类方法

类方法是用于描述类的行为的方法,类方法属于类,不属于该类创建的对象

说明:

        类方法需要使用@classmethod装饰器定义
        类方法至少有一个形参用于绑定类,约定为 $cls$
        类和该类的实例都可以调用类方法
        类方法不能访问此类创建的对象的实例属性

类方法示例1

class A:
    v = 0

    @classmethod
    def set_v(cls, value):
        cls.v = value

    @classmethod
    def get_v(cls):
        return cls.v


print(A.get_v())
A.set_v(100)
print(A.get_v())
a = A()
print(a.get_v())

类方法示例2

class MyClass:
    class_attr = 0  # 类属性

    def __init__(self, value):
        self.instance_attr = value  # 实例属性

    @classmethod
    def modify_class_attr(cls, new_value):
        cls.class_attr = new_value
        print(f"类属性已修改为: {cls.class_attr}")

    @classmethod
    def try_modify_instance_attr(cls):
        try:
            cls.instance_attr = 10  # 事出反常必有妖
        except AttributeError as e:
            print(f"错误: {e}")


# 创建类的实例
obj = MyClass(5)

# 调用类方法修改类属性
MyClass.modify_class_attr(20)  # 输出: 类属性已修改为: 20
MyClass.try_modify_instance_attr()	# 事出反常必有妖


5. 静态方法

静态方法定义在类的内部,作用域是类内部

说明:

        使用@staticmethod装饰器定义
        不需要self和cls参数**
        通过类或类实例调用
        可以访问类属性,不能访问实例属性

使用场景:

        逻辑上属于类的方法,但不依赖类或实例
        让代码更有组织性
        避免污染全局命名空间

静态方法示例:

class A:
    class_attr = 42  # 类属性

    def __init__(self, value):
        self.instance_attr = value  # 实例属性

    @staticmethod
    def myadd(a, b):
        # 只能访问传递的参数,不能访问实例属性
        return a + b

# 创建类实例
a = A(10)

# 调用静态方法
print(A.myadd(100, 200))  # 输出: 300
print(a.myadd(300, 400))  # 输出: 700


5.1 综合应用

小案例:

class BankAccount:
    interest_rate = 0.05  # 类属性

    def __init__(self, balance):
        self.balance = balance

    def apply_interest(self):  # 实例方法
        self.balance *= (1 + self.interest_rate)

    @classmethod
    def set_interest_rate(cls, rate):  # 类方法
        cls.interest_rate = rate

    @staticmethod
    def validate_amount(amount):  # 静态方法
        return amount > 0  # 只是个工具方法,不依赖实例/类

# 使用类方法修改利率
BankAccount.set_interest_rate(0.07)

# 创建账户
acc = BankAccount(1000)
acc.apply_interest()
print(acc.balance)  # 1070.0

# 使用静态方法验证金额
print(BankAccount.validate_amount(-500))  # False


6. 构造方法

构造方法  __new__():

  负责对象的 **创建** 和内存分配的。
  在对象实例化时被调用,负责返回一个新的对象实例。
  通常不需要显式地定义 __new__() 方法,Python会调用基类 object 的 __new__() 方法。

class MyClass:
    def __new__(cls, *args, **kwargs):
        print("调用 __new__ 方法,创建对象")
        return super().__new__(cls)

    def __init__(self, value):
        print("调用 __init__ 方法,初始化对象")
        self.value = value


# 创建对象
obj = MyClass(10)

7. 初始化方法

一旦对象被创建,Python会调用 __init__() 来初始化对象的属性。

语法格式:

class 类名(继承列表):
    def __init__(self[, 形参列表]):
        语句块
# [] 代表其中的内容可省略

接收实参到  __init__ 方法中

代码示例:

class MyClass:
    def __new__(cls, *args, **kwargs):
        print("调用 __new__ 方法,创建对象")
        return super().__new__(cls)

    def __init__(self, value):
        print("调用 __init__ 方法,初始化对象")
        self.value = value

# 创建对象
obj = MyClass(10)

#输出
"""
调用 __new__ 方法,创建对象
调用 __init__ 方法,初始化对象
"""

8. 魔术方法

魔术方法是一种特殊的方法,用双下划线包裹,例如 __init__ , __str__ , __add__ 等。这些方法允许您自定义类的行为,以便与内置Python功能(如+运算符、迭代、字符串表示等)交互。


8.1 常用方法

1.  __init__(self, ...) : 初始化对象,通常用于设置对象的属性。
2.  __str__(self) : 定义对象的字符串表示形式,可通过 str(object) 或 print(object) 调用。例如,您可以返回一个字符串,描述对象的属性。
3.  __repr__(self) : 定义对象的“官方”字符串表示形式,通常用于调试。可通过`repr(object)`调用。
4.  __len__(self) : 定义对象的长度,可通过`len(object)`调用。通常在自定义容器类中使用。
5.  __getitem__(self, key) : 定义对象的索引操作,使对象可被像列表或字典一样索引。例如, object[key] 。
6.  __setitem__(self, key, value) : 定义对象的赋值操作,使对象可像列表或字典一样赋值。例如, object[key] = value 。
7.  __delitem__(self, key) : 定义对象的删除操作,使对象可像列表或字典一样删除元素。例如, del object[key] 。
8.  __iter__(self) : 定义迭代器,使对象可迭代,可用于 for 循环。
9.  __next__(self) : 定义迭代器的下一个元素,通常与 __iter__ 一起使用。
10.  __add__(self, other) : 定义对象相加的行为,使对象可以使用 + 运算符相加。例如, object1 + object2 。
11.  __sub__(self, other) : 定义对象相减的行为,使对象可以使用 - 运算符相减。
12.  __eq__(self, other) : 定义对象相等性的行为,使对象可以使用 == 运算符比较。
13.  __lt__(self, other) : 定义对象小于其他对象的行为,使对象可以使用 < 运算符比较。
14.  __gt__(self, other) : 定义对象大于其他对象的行为,使对象可以使用 > 运算符比较。
15.  __call__(self, other) 是一个特殊的方法(也称为“魔法方法”),它允许一个对象像函数一样被调用。


8.2 案例参考

1、__str__() :定义  print()  或  str()  函数调用时的输出字符串表示。

      __str__()  方法用来定义当你调用  print()  或  str()  时对象应该返回的字符串。
      该方法必须返回一个字符串,通常用于给用户可读的对象描述。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"Person: {self.name}, Age: {self.age}"

p = Person("Alice", 30)
print(p)  # 输出: Person: Alice, Age: 30

作用:

        使得你的对象在打印时更加友好和可读。

        提供更好的调试输出。

2、 __repr__() :定义  repr()  函数的输出,通常用于开发和调试,给出对象的正式字符串表示。

       __repr__()  方法用于返回一个可以用来重新创建对象的字符串,理想情况下,返回的字符串应当是合法的 Python 表达式。
       如果你没有定义  __str__() ,那么  __repr__()  会被用来替代  str()  和  print() 。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f"Person('{self.name}', {self.age})"

p = Person("Alice", 30)
print(repr(p))  # 输出: Person('Alice', 30)

作用:

       __repr__() 是供开发人员使用的,输出的字符串应该尽可能接近于可以创建该对象的代码。

       在调试时使用 repr() 更加方便,它提供了一个清晰的对象表示。

因为就不一一来举例了,我们用一个小小的综合案例:

题目:​​ 创建一个简单的Fraction(分数)类。
​要求支持:​​
1、创建 (__init__)
2、字符串表示 (__str__)
3、精确表示 (__repr__)
4、相等比较 (__eq__)
5、加法 (__add__)
6、约分(辅助方法)

class Fraction:
    #一个简单的分数类
    def __init__(self, numerator, denominator=1):
        #初始化分子和分母。分母不能为0。自动约分。
        if denominator == 0:
            raise ValueError("分母不能为0!")
        self.numer = numerator   # 分子
        self.denom = denominator # 分母
        self._simplify()         # 在创建时就进行约分

    def _gcd(self, a, b):
        #计算最大公约数 (gcd) 的辅助函数
        while b:
            a, b = b, a % b
        return a

    def _simplify(self):
        #约分私有方法
        g = self._gcd(abs(self.numer), abs(self.denom))
        self.numer //= g
        self.denom //= g
        # 处理符号,保证分母为正 (分子带符号)
        if self.denom < 0:
            self.numer = -self.numer
            self.denom = -self.denom

    def __str__(self):
        #友好的字符串表示:3/4
        return f"{self.numer}/{self.denom}"

    def __repr__(self):
        #无歧义表示:Fraction(3,4)
        return f"Fraction({self.numer}, {self.denom})"

    def __eq__(self, other):
        #定义相等:约分后的分子分母分别相等即为相等
        if not isinstance(other, Fraction):
            return False # 也可以尝试类型转换
        return self.numer == other.numer and self.denom == other.denom

    def __add__(self, other):
        #分数加法: (a/b) + (c/d) = (ad+bc)/(bd)
        if not isinstance(other, Fraction):
            raise TypeError("只能与另一个Fraction相加")
        new_numer = self.numer * other.denom + other.numer * self.denom
        new_denom = self.denom * other.denom
        return Fraction(new_numer, new_denom)  # 返回新的约分后的分数对象

# 使用示例
f1 = Fraction(3, 4)
f2 = Fraction(1, 8)
print(f1)              # 输出: 3/4
print(repr(f1))        # 输出: Fraction(3, 4) (或接近形式)
print(f1 + f2)          # 输出: 7/8 (会自动约分)
f3 = Fraction(1, 2)
f4 = Fraction(2, 4)
print(f3 == f4)        # 输出: True (约分后都是1/2)

这个例子展示了如何利用魔术方法让自定义的Fraction类拥有与Python内置类型类似的行为和接口:自然创建、易读打印、精确描述、自定义相等性判断以及直观的加法运算符。


总结

这一章讲解了面向对象编程,讲述了oop的核心:类与对象,类是对象的蓝图,定义属性和其方法;对象是类的具体实例。属性分为实例属性和类属性;方法包括实例方法、类方法和静态方法。魔术方法自定义对象行为,实现代码复用和扩展。这一章可能有点绕,但只要了解代码内部的逻辑,大多都是简单的。

你可能感兴趣的:(python基础篇,python,分类,开发语言,学习)