AI项目博客
记录 AI 工程实践与大模型应用

Python 学习笔记 16|实例属性、类属性

3. 实例属性、类属性

3.1. 实例属性

1️⃣定义:通过实例.属性名 = 值定义在实例身上的属性,称为:实例属性。

2️⃣特点:

  • 每个实例都有自己『独立的一份』实例属性,各个实例之间是互不影响的。
  • 实例属性只能通过实例.xxxx访问和修改,不能通过『类名』访问或修改。
# 定义一个Person类
class Person:
    # 初始化方法
    def __init__(self, name, age, gender):
        # 通过【实例.属性名 = 值】给实例添加的属性,就叫实例属性
        # 实例属性只能通过实例访问,不能通过类访问
        # 每个实例都有自己【独一份的】实例属性,各个实例之间是互不干扰的
        self.name = name
        self.age = age
        self.gender = gender

# 创建Person类的实例对象
p1 = Person('张三', 18, '男')
p2 = Person('李四', 22, '女')

# 实例属性只能通过实例访问,不能通过类访问
print(p1.name)
print(Person.name)

3.2. 类属性

1️⃣定义: 在类中直接写赋值语句(例如:a = 100),就会在类身上添加一个a属性,值为 100,此时的a就是『类属性』,它属于类本身,由类所拥有,并且该类创建出来的所有实例对象,都能去访问a属性。

2️⃣特点:

  • 所有实例访问的,都是同一个类属性,所以类属性通常用于:存放公共数据。
  • 类属性即可以通过『类』访问,也可以『实例』访问。
# 定义一个Person类
class Person:
    # max_age、planet 他们都是类属性,类属性是保存在类身上的
    # 类属性可以通过类访问,也可以通过实例访问
    # 类属性通常用于保存:公共数据
    max_age = 120
    planet = '地球'

    # 初始化方法
    def __init__(self, name, age, gender):
        # 给实例添加属性
        self.name = name
        self.gender = gender
        # 限制age的最大值
        if age <= Person.max_age:
            self.age = age
        else:
            print(f'年龄超出范围了,已经将年龄设置为最大值:{Person.max_age}')
            self.age = Person.max_age

# 验证一下:类属性是保存在类身上的
# print(Person.__dict__)

# 创建Person类的实例对象
p1 = Person('张三', 18, '男')
p2 = Person('李四', 22, '女')

# 验证一下:实例身上是没有类属性的
# print(p1.__dict__)
# print(p2.__dict__)

# 验证一下:类属性可以通过类访问,也可以通过实例访问
# print(Person.max_age)
# print(p1.max_age)  # 查找max_age的过程:1.实例自身(p1)  => 2.实例的“缔造者”(Person)
# print(p2.planet)

# 测试一下年龄超出范围
# p3 = Person('王五', 170, '女')
# print(p3.__dict__)

3️⃣特别注意:

进行实例.属性名 = xxx操作时,只会对实例自身的属性起作用(有则修改,无则添加)!

# 注意点:进行【实例.属性名 = 值】操作时,只会对实例自身的属性起作用,不会影响类属性
p1.planet = '火星'
print(Person.__dict__)
print(p1.__dict__)
print(p2.__dict__)
print(p1.planet)
print(p2.planet)

4. 实例方法、类方法、静态方法

4.1. 实例方法

定义:类中所定义的方法,最终会保存在类身上,并且主要是通过实例调用,所以叫:实例方法。

特点:

  • 实例方法虽然最终会保存在类身上,但它主要是供实例使用的,所以才叫实例方法。
  • 因为收到了self参数,所以其内部可以:访问实例属性,调用实例方法。
  • 实例方法的主要作用:定义实例对象的具体行为。
# 定义一个Person类
class Person:
    # 初始化方法(给实例添加属性)
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    # 下面的speak方法、run方法,都保存在类身上,但他们主要是供实例调用,所以他们都叫:实例方法
    # 自定义方法(给实例添加行为)
    def speak(self, msg):
        print(f'我叫{self.name}, 年龄是{self.age}, 性别是{self.gender},我想说:{msg}')

    # 自定义方法(给实例添加行为)
    def run(self, distance):
        print(f'{self.name}疯狂的奔跑了{distance}米')

# 创建Person类的实例对象
p1 = Person('张三', 18, '男')
p2 = Person('李四', 22, '女')

print(Person.__dict__)
print(p1.__dict__)
print(p2.__dict__)

# 通过实例调用实例方法
p1.speak('你好')
p1.run(300)

# 通过类去调用实例方法(能调用,但不推荐)
Person.run(p2, 100)

4.2. 类方法

定义:使用@classmethod装饰器修饰,第一个参数是类本身,通常用形参cls接收。

特点:

  • 可通过『类名』或『实例名』调用,但强烈推荐通过类名调用以体现语义。
  • 因为收到了cls参数,所以内部可以访问类属性。
  • 一般用于:实现与类相关的逻辑,如:操作类级别的信息、工厂方法等。
from datetime import datetime

# 定义一个Person类
class Person:
    # 类属性
    max_age = 120
    planet = '地球'

    # 初始化方法(给实例添加属性)
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    # speak方法、run方法,他们都属于:实例方法
    def speak(self, msg):
        print(f'我叫{self.name}, 年龄是{self.age}, 性别是{self.gender},我想说:{msg}')

    def run(self, distance):
        print(f'{self.name}疯狂的奔跑了{distance}米')

    # 使用 @classmethod 装饰过的方法,就叫:类方法,类方法保存在类身上的
    # 类方法收到的参数:当前类本身(cls)、自定义的参数
    # 因为收到了cls参数,所以类方法中是可以访问类属性的
    # 类方法通常用于实现:与类相关的逻辑,例如:操作类级别的信息、一些工厂方法
    @classmethod
    def change_planet(cls, value):
        cls.planet = value

    @classmethod
    def create(cls, info_str):
        # 从info_str中获取到有效信息
        name, year, gender = info_str.split('-')
        # 获取当前年份
        current_year = datetime.now().year
        # 计算年龄
        age = current_year - int(year)
        # 创建并返回一个Person类的实例对象
        return cls(name, age, gender)

# 验证一下:类方法保存在类身上的
# print(Person.__dict__)

# 类方法需要通过类调用
# Person.change_planet('月球')
# print(Person.__dict__)

# 创建Person实例
p1 = Person('张三', 18, '男')
p2 = Person('李四', 22, '女')

# 验证一下:类属性planet已经修改了
# print(p1.planet)
# print(p2.planet)

# 测试一下类方法 —— create
# p3 = Person.create('李华-2003-女')
# print(p3.__dict__)

# 注意点:类方法,也能通过实例调用到,但是非常不推荐
p4 = p1.create('李华-2003-女')
print(p4.__dict__)

4.3. 静态方法

定义:使用@staticmethod装饰器修饰,方法没有self或cls参数,只是单纯的定义在类中。

特点:

  • 可通过『类名』或『实例名』调用,但强烈推荐通过类名调用以体现语义。
  • 由于没有self或cls参数,所以静态方法中通常:不访问类属性,也不访问实例属性。
  • 一般用于:定义与类相关,但可以独立使用的工具方法。
# 定义一个Person类
class Person:
    # *******************************
    # *******************************
    # *******************************

    # 静态方法
    # 使用 @staticmethod 装饰过的方法,就叫:静态方法,静态方法也是保存在类身上的
    # 静态方法只是单纯的定义在类中,它不会收到:self、cls参数,它收到的参数都是自定义参数
    # 由于静态方法没有收到:self、cls参数,所以其内部不会访问任何:类和实例相关的内容
    # 静态方法通常用于定义:与类相关的工具方法
    @staticmethod
    def is_adult(year):
        # 获取当前的年份
        current_year = datetime.now().year
        # 计算年龄
        age = current_year - year
        # 返回结果(成年True,未成年False)
        return age >= 18

    @staticmethod
    def mask_idcard(idcard):
        return idcard[:6] + '********' + idcard[-4:]

# 验证一下:静态方法也是保存在类身上的
# print(Person.__dict__)

# 静态方法需要通过类去调用
# result = Person.is_adult(2015)
# print(result)
# result2 = Person.mask_idcard('212101198802030028')
# print(result2)

# 注意点:通过实例也能调用到静态方法,但非常不推荐
p1 = Person('张三', 18, '男')
res = p1.mask_idcard('212101198802030028')
print(res)

5. 继承

5.1. 基本语法

概念:是指一个类,可以继承另一个类的属性和方法。

作用:可以实现代码的复用与扩展,避免重复编写相同的代码,让程序结构更简洁、更高效。

举例:就像生活中,孩子可以继承父母的:长相、性格、财产等,程序中的继承与之类似。

代码实例:

如下代码中Person为父类(又称:基类)Student为子类(又称:派生类)

# 定义一个Person类
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def speak(self, msg):
        print(f'我叫{self.name}, 年龄是{self.age}, 性别是{self.gender},我想说:{msg}')

# 定义一个Student类(子类、派生类), 继承自Person类(父类、超类、基类)
class Student(Person):
    def __init__(self, name, age, gender, stu_id, grade):
        # 在子类中,有两种方式去调用父类的初始化方法,来实现对继承属性:name, age, gender 初始化操作
        # 方式1(更推荐)
        super().__init__(name, age, gender)

        # 方式2
        # Person.__init__(self, name, age, gender)

        # 子类独有的属性,需要自己手动完成初始化
        self.stu_id = stu_id
        self.grade = grade

    def study(self):
        print(f'我叫{self.name},我在努力的学习,争取做到{self.grade}年级的第一名')

# 创建Student类的实例对象
s1 = Student('李华', 16, '男', '2025001', '初二')
# print(s1.__dict__)
# print(type(s1))

# 查找speak方法的过程:1.实例自身(s1) => 2.Student类 => 3.Person类
# s1.speak('你好')

# print(s1.__dict__)

# 查找study方法的过程:1.实例自身(s1) => 2.Student类 => 3.Person类
# s1.study()

几个说明:

  • 定义类时,在类名后写圆括号(),并填入另一个类名,表示该类继承自另一个类。
  • 在子类中,可以直接使用父类中定义的:属性、方法,也可以定义自己独有的内容。
  • super().__init__()的作用:调用父类的初始化方法。

5.2. 方法重写

如果子类中定义了与父类同名的方法,则会子类会“覆盖”父类中的方法,又称:“重写”。

# 定义一个Person类
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

    def speak(self, msg):
        print(f'我叫{self.name}, 年龄是{self.age}, 性别是{self.gender},我想说:{msg}')

# 定义一个Student类,继承自Person类
class Student(Person):
    def __init__(self, name, age, gender, stu_id, grade):
        super().__init__(name, age, gender)
        self.stu_id = stu_id
        self.grade = grade

    # 方法重写:当子类中定义了一个与父类中相同的方法,那么子类中的方法就会“覆盖”父类的方法
    def speak(self, msg):
        super().speak(msg)
        print(f'我是学生,我的学号是{self.stu_id},我正在读{self.grade},我想说:{msg}')

s1 = Student('李华', 12, '男', '2025001', '初二')
s1.speak('好好学习')

5.3. isinstance() 和 issubclass()

两个常用方法:

函数 作用
isinstance(obj, Class) 判断对象是否为指定类或其子类的实例
issubclass(Sub, Super) 判断一个类是否是另一个类的子类
# 定义一个Person类
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender

# 定义一个Student类,继承自Person类
class Student(Person):
    def __init__(self, name, age, gender, stu_id, grade):
        super().__init__(name, age, gender)
        self.stu_id = stu_id
        self.grade = grade

p1 = Person('张三', 18, '男')
s1 = Student('李华', 12, '男', '2025001', '初二')

# 方法1:isinstance(instance, Class),作用:判断某个对象是否为指定类或其子类的实例
print(isinstance(s1, Student))
print(isinstance(p1, Person))
print(isinstance(s1, Person))
print(isinstance(p1, Student))

# 方法2:issubclass(Class1, Class2),作用:判断某个类是否是另一个类的子类
print(issubclass(Student, Person))
print(issubclass(Person, Student))

5.4. 多重继承

概念:多重继承指一个类同时继承多个父类,从而拥有多个父类的属性和方法。

举例:就像孩子不仅继承爸爸的长相,还可能继承妈妈的性格。

class 子类名(父类A, 父类B, ...):
    # 子类可以继承多个父类的属性和方法
    ...

代码示例:如下代码中Student类同时继承Person类和Worker类。

# 所谓多重继承,就是一个类,可以同时继承多个父类
# 定义一个Person类
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
    def speak(self):
        print(f'我叫{self.name}, 年龄是{self.age}, 性别是{self.gender}')

# 定义一个Worker类
class Worker:
    def __init__(self, company):
        self.company = company
    def do_work(self):
        print(f'我在{self.company}做兼职')

# 定义一个Student类,继承自:Person类、Worker类
class Student(Person, Worker):
    def __init__(self, name, age, gender, stu_id, grade, company):
        Person.__init__(self, name, age, gender)
        Worker.__init__(self, company)
        self.stu_id = stu_id
        self.grade = grade
    def study(self):
        print(f'我在很努力的学习,争取做{self.grade}年级的第一名')

# 创建Student实例对象
s1 = Student('张三', 18, '男', '2025001', '初二', '麦当劳')
print(s1.__dict__)
s1.speak()
s1.do_work()
s1.study()

# 类的__mro__属性:用于记录属性和方法的查找顺序
# 通过实例去查找属性或方法时,会现在实例自身上寻找,如果没有,就按照__mro__中所记录的顺序去查找
print(Student.__mro__)
赞(0)
未经允许不得转载:AI项目博客 » Python 学习笔记 16|实例属性、类属性

评论 抢沙发

AI项目博客

专注 AI 工程化落地 —— 覆盖智能体、大模型、Java AI 与 Python 的学习笔记,以及 AI 平台的项目实战记录。

关于本站文章归档

登录

找回密码

注册