Python训练打卡Day28

类的定义方法

知识点回顾

  1. 定义
  2. pass占位语句
  3. 初始化方法
  4. 类的普通方法
  5. 类的继承属性继承方法继承

类是对属性和方法的封装,可以理解为模板,通过对模板实例化可以实现调用这个类的属性和方法。比如创建一个随机森林类,然后就可以调用他的训练和预测方法。

一个常见的类的定义包括了:

1. 关键字class

2. 类名

3. 语法固定符号冒号(:)

4. 一个初始化函数__init__(self)  

注意:注意:init左右各有两个下划线__,需要传入self这个特殊的参数。

Pass占位符和缩进
class ClassName: # 类名通常遵循大驼峰命名法 (UpperCamelCase),即每个单词的首字母都大写,class是定义类的关键词
    # 类的代码块 (可以包含属性定义、方法定义等)
    pass # pass 是一个占位符,表示这里暂时没有任何内容

许多时候,当规划好准备写一个函数、或者一个类,关键词定义后,会先用pass占位,避免运行错误,等到想好写什么再去补上

# 条件语句
x = 10
if x > 5:
    pass# 如果这里是空的,就会报错,可以注释试一下,即使x=1也会报错
else:
    print("x is not greater than 5")

总结:

        Python 通过缩进来定义代码块的结构。当解释器遇到像 def, class, if, for 这样的语句,并且后面跟着冒号 : 时,它就期望接下来会有一个或多个缩进的语句来构成这个代码块。如果它没有找到任何缩进的语句(即代码块是空的),它就无法确定这个结构的范围,因此会抛出 IndentationError。

        pass 语句的存在就是为了解决这个问题:它本身不执行任何操作,但它是一个有效的 Python 语句。所以,当你需要一个语法上存在的代码块,但又暂时不想在其中放入任何实际的逻辑时,pass 就是一个完美的占位符,它告诉解释器:“这里有一个代码块,但它什么也不做。”

类的初始化方法

初始化方法又叫构造方法、特殊方法

类有2种方法

1. 初始化方法,

2. 普通放大

class Teacher: # 这里不需要括号
  def __init__(self): #初始化方法,这里没有传入参数
    self.name = "Susan" # 给类定义一些属性
    self.subject = "English"
    self.age = 33

Teacher = Teacher() # 创建一个Teacher类的实例
print(Teacher.name) # 输出: Susan
class Teacher:
    def __init__(self, name, age):# 初始化方法,传入了参数
        self.name = name # 外界的参数,需要通过self.xxx来复制给类自己的属性
        self.age = age
        self.subject = "English"  # 这个属性仍然是在创建时就设定好的

# 创建一个Teacher对象的例子,构造方法的参数必须
teacher = Teacher("Susan", 33) # 如果在初始化方法中设置了非默认的参数,那么外界就必须要传入才行
print(teacher.name)  # 输出: Susan
print(teacher.age)   # 输出: 33
print(teacher.subject)  # 输出: English

        其中,self.xx是用来表明这个属性“归属于”这个类自己的(self)。比如self.name,就代表着:“自己的名字”,self等于“自己”,这个self指向类的实例化地址,传入的self.xx是它的属性。

        以后要是用它的属性值,即使是从外界参数传入的,前面也必须加上self.xx,否则传入的参数没价值(例外的情况我们不提)

类的普通方法

        除了init方法(初始化方法,又名构造方法),还包含一些普通方法(自己定义)

        普通方法和init方法的差别在于,init方法是类的构造方法,当创建对象时,会自动调用init方法----只要你创建这个类对象了,这个init函数就会执行

        普通方法是只有你调用类的这个方法的时候,函数才会执行

class Teacher:
    def __init__(self):
        self.name = "Susan"
        self.subject = "English"
        self.age = 33
    def teach_lesson(self):
        print("上课中")
    def criticize(self):
        print("批评人") 
t = Teacher()
t.teach_lesson() # 调用类的方法
t.criticize()
print(t.name)
# 定义一个名为 Teacher 的类,用于表示教师对象
class Teacher:
    # 类的构造函数,在创建 Teacher 类的实例时自动调用
    # name: 教师的姓名
    # age: 教师的年龄
    # gender: 教师的性别
    # subject: 教师教授的学科
    def __init__(self, name, subject, age, gender):
        # 将传入的姓名赋值给实例属性 name
        self.name = name
        # 将传入的学科赋值给实例属性 subject
        self.subject = subject
        # 将传入的年龄赋值给实例属性 age
        self.age = age
        # 将传入的性别赋值给实例属性 gender
        self.gender = gender
    
    # 定义一个实例方法,用于表示教师正在授课
    def teacher_lesson(self):
        # 打印教师正在教授课程的信息
        print(f"{self.name}正在教{self.subject}。")

    # 定义一个实例方法,用于表示教师正在批评学生
    # student_name: 被批评学生的姓名
    def criticize_student(self, student_name):
        # 打印教师正在批评学生的信息
        print(f"{self.name}正在批评{student_name}。")

# 创建一个 Teacher 类的实例,传入姓名、学科、年龄和性别
teacher = Teacher("Susan", "English", 33, "Female")

# 调用 teacher_lesson 方法,输出教师授课信息
teacher.teacher_lesson()
# 调用 criticize_student 方法,传入学生姓名,输出教师批评学生的信息
teacher.criticize_student("John")

类的继承

类已经是比较优秀的封装了,封装了函数、封装了属性。正如装饰器进一步封装了函数的可复用的功能,装饰器函数封装了函数。那么有没有东西可以进一步封装类呢?这就引出了类的继承。在面向对象编程中,继承允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码复用和功能扩展。子类可以:

1. 复用父类的代码(无需重新实现)。

2. 重写父类的方法(修改或增强功能)。

3. 添加新的方法和属性(扩展功能)。

# 先沿用之前定义的teacher类
class Teacher:
    def __init__(self, name, subject, age):
        self.name = name
        self.subject = subject
        self.age = age

    def teach_lesson(self):
        print(f"{self.name}正在教{self.subject}。")

    def criticize(self, student_name):
        print(f"{self.name}正在批评{student_name}。")

# 继承 Teacher 类,起名特级教师
class MasterTeacher(Teacher): # 1. 继承需要在括号中指定父类
    def __init__(self, name, subject, age, experience_years):# 2. 继承的时候需要调用父类的构造方法,所以需要传入父类的参数,同时也可以传入自己的参数
        # 调用父类的构造方法初始化基本属性
        super().__init__(name, subject, age) # 3. 调用父类的构造方法,这里的super()是一个内置函数,返回父类的实例
        # 4. 此时子类自动拥有了父类的属性和方法
        # 添加子类特有的属性

        self.experience_years = experience_years # 5. 子类特有的属性可以在这里定义

    # 重写父类方法,增强功能-----如果子类定义了与父类同名的方法,子类实例会优先调用子类的方法。
    def teach_lesson(self): # 6. 重写父类的方法
        print(f"{self.name}(特级教师)正在用高级方法教授{self.subject}。")

    # 新增子类特有的方法
    def give_lecture(self, topic): 
        print(f"{self.name}正在举办关于{topic}的讲座。")

# 创建子类实例
master = MasterTeacher("王教授", "数学", 45, 20)

# 调用继承的方法
master.teach_lesson()     # 调用重写的父类的方法
master.criticize("李同学")  # 调用父类的方法,如果不修改方法,则可以直接继承父类的方法

# 调用子类特有的方法
master.give_lecture("微积分")  # 调用子类新增的方法
# super()函数 除了在构造方法中使用,还可以在其他方法中使用

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

    def speak(self):
        print(f"{self.name} 发出声音")
    
class Dog(Animal):
    def speak(self):
        super().speak()  # 先调用父类的方法
        print("汪汪叫")    # 再添加子类的行为

dog = Dog("旺财", 3)
dog.speak() 

所以重写父类的方法,也包含2种

1. 直接重写:本质是会优先用子类的同名方法,完全替代父类方法,父类逻辑不会执行。

2. 使用super()重写,保留父类方法的核心逻辑,并在其基础上扩展。

题目1:定义圆(Circle)类

要求:

  1. 包含属性:半径 radius。
  2. 包含方法:
  • calculate_area():计算圆的面积(公式:πr²)。
  • calculate_circumference():计算圆的周长(公式:2πr)。
  1. 初始化时需传入半径,默认值为 1。
import math

class Circle:
    """
    一个表示圆的类,包含计算面积和周长的方法。
    """
    def __init__(self, radius=1):
        """
        初始化 Circle 实例,设置半径,默认为 1。
        
        参数:
        radius (float): 圆的半径。默认值为 1。
        """
        self.radius = radius
    
    def calculate_area(self):
        """
        计算并返回圆的面积。
        
        返回:
        float: 圆的面积。
        """
        return math.pi * (self.radius ** 2)
    
    def calculate_circumference(self):
        """
        计算并返回圆的周长。
        
        返回:
        float: 圆的周长。
        """
        return 2 * math.pi * self.radius


# 创建一个半径为5的圆
circle = Circle(5)

# 计算并打印圆的面积
print(f"圆的面积: {circle.calculate_area()}")   # 输出示例: 圆的面积: 78.53981633974483

# 计算并打印圆的周长
print(f"圆的周长: {circle.calculate_circumference()}") # 输出示例: 圆的周长: 31.41592653589793

# 使用默认半径创建一个圆
default_circle = Circle()
print(f"默认圆的面积: {default_circle.calculate_area()}") # 输出示例: 默认圆的面积: 3.141592653589793
print(f"默认圆的周长: {default_circle.calculate_circumference()}") # 输出示例: 默认圆的周长: 6.283185307179586

题目2:定义长方形(Rectangle)类

  1. 包含属性:长 length、宽 width。
  2. 包含方法:
  • calculate_area():计算面积(公式:长×宽)。
  • calculate_perimeter():计算周长(公式:2×(长+宽))。 is_square() 方法,判断是否为正方形(长 == 宽)。
  1. 初始化时需传入长和宽,默认值均为 1。
class Rectangle:
    """
    一个表示长方形的类,包含计算面积、周长的方法,并可以判断是否为正方形。
    """
    def __init__(self, length=1, width=1):
        """
        初始化 Rectangle 实例,设置长和宽,默认值均为 1。

        参数:
        length (float 或 int): 长方形的长度。
        width (float 或 int): 长方形的宽度。
        """
        self.length = length
        self.width = width

    def calculate_area(self):
        """
        计算并返回长方形的面积。

        返回:
        float: 长方形的面积。
        """
        return self.length * self.width

    def calculate_perimeter(self):
        """
        计算并返回长方形的周长。

        返回:
        float: 长方形的周长。
        """
        return 2 * (self.length + self.width)

    def is_square(self):
        """
        判断该长方形是否是一个正方形(长等于宽)。

        返回:
        bool: 如果是正方形则返回 True,否则返回 False。
        """
        return self.length == self.width


# 创建一个长方形对象
rect = Rectangle(4, 6)

print(f"面积: {rect.calculate_area()}")         # 输出:面积: 24
print(f"周长: {rect.calculate_perimeter()}")    # 输出:周长: 20
print(f"是否为正方形: {rect.is_square()}")      # 输出:是否为正方形: False

# 创建一个正方形对象
square = Rectangle(5, 5)

print(f"面积: {square.calculate_area()}")       # 输出:面积: 25
print(f"周长: {square.calculate_perimeter()}")  # 输出:周长: 20
print(f"是否为正方形: {square.is_square()}")    # 输出:是否为正方形: True

# 使用默认值创建长方形
default_rect = Rectangle()

print(f"默认面积: {default_rect.calculate_area()}")         # 输出:默认面积: 1
print(f"默认周长: {default_rect.calculate_perimeter()}")    # 输出:默认周长: 4
print(f"是否为正方形: {default_rect.is_square()}")          # 输出:是否为正方形: True

题目3:图形工厂

创建一个工厂函数 create_shape(shape_type, *args),根据类型创建不同图形对象:图形工厂(函数或类)

shape_type="circle":创建圆(参数:半径)。

shape_type="rectangle":创建长方形(参数:长、宽)。

import math

# Circle 类定义(如题1)
class Circle:
    def __init__(self, radius=1):
        self.radius = radius
    
    def calculate_area(self):
        return math.pi * (self.radius ** 2)
    
    def calculate_circumference(self):
        return 2 * math.pi * self.radius


# Rectangle 类定义(如题2)
class Rectangle:
    def __init__(self, length=1, width=1):
        self.length = length
        self.width = width

    def calculate_area(self):
        return self.length * self.width

    def calculate_perimeter(self):
        return 2 * (self.length + self.width)

    def is_square(self):
        return self.length == self.width


# 工厂函数 create_shape
def create_shape(shape_type, *args):
    """
    图形工厂函数,根据 shape_type 创建相应的图形对象。

    参数:
    shape_type (str): 图形类型,可选 'circle' 或 'rectangle'
    *args: 创建图形所需的参数:
           - circle 需要一个参数:radius
           - rectangle 需要两个参数:length, width

    返回:
    object: 对应类型的图形实例,如果类型不支持则返回 None
    """
    if shape_type == "circle":
        if len(args) == 0:
            return Circle()
        elif len(args) == 1:
            return Circle(radius=args[0])
        else:
            raise ValueError("Circle 需要 0 或 1 个参数")
    
    elif shape_type == "rectangle":
        if len(args) == 0:
            return Rectangle()
        elif len(args) == 2:
            return Rectangle(length=args[0], width=args[1])
        else:
            raise ValueError("Rectangle 需要 0 或 2 个参数")
    
    else:
        raise ValueError(f"不支持的图形类型: {shape_type}")


# 创建圆
c1 = create_shape("circle")                  # 默认半径
c2 = create_shape("circle", 5)               # 半径为5

print("Circle 1 面积:", c1.calculate_area())
print("Circle 2 周长:", c2.calculate_circumference())

# 创建长方形
r1 = create_shape("rectangle")               # 默认长宽
r2 = create_shape("rectangle", 4, 6)         # 长4,宽6

print("Rectangle 1 是否正方形:", r1.is_square())
print("Rectangle 2 面积:", r2.calculate_area())

@浙大疏锦行

你可能感兴趣的:(Python学习笔记,python,开发语言)