Day 28 类的定义和方法

@浙大疏锦行

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

类的定义

对类进行定义时,使用class关键字,注意与函数不同,在类名的后面不需要加括号,示例如下:

class ClassName: #类名通常遵循大驼峰命名法 (UpperCamelCase),即每个单词的首字母都大写
    """类的文档字符串"""
    # 类的内容
    pass #pass 为占位符,避免运行错误

关于pass与缩进:

  • Python通过缩进定义代码块的结构,对于def,class,if等,如果后续代码块为空,那么就会因为无法确定结构的范围而抛出IndentationError。
  • pass本身不执行任何操作,但它可以起到一个占位置的作用。因此,当需要一个语法上存在的代码块,但又暂时不想在其中放入任何实际的逻辑时,就可以使用pass占位。

在定义一个类时,它可以具有属性和方法两个部分。

  • 属性(是什么):用于存储数据,初始化方法构造类内部直接定义、类外部添加
  • 方法(做什么):定义行为,初始化方法(__init__)、类方法、静态方法、魔术方法等等

类的方法

上面提到了类的方法和属性,在调用时,对方法和属性分别使用example.method()、example.name。

下面主要说明初始化方法和自定义的普通方法。

初始化方法

__init__(注意前后均各有两条下划线)属于类的构造方法,当创建对象时,会被自动调用

关于参数,可以自己使用self.属性名给出默认值或者赋值给外部传入的参数值。

class Teacher:
    def __init__(self, name, age):# 初始化方法,传入了参数
        print(f"self的内存地址: {id(self)}") #打印内存地址
        self.name = name # 外界的参数,需要通过self.xxx来复制给类自己的属性
        self.age = age
        self.subject = "English"  # 这个属性仍然是在创建时就设定好的

# 创建一个Teacher对象的例子,构造方法的参数必须
teacher_1 = Teacher("Susan", 33) # 如果在初始化方法中设置了非默认的参数,那么外界就必须要传入才行
print(f"teacher_1的内存地址: {id(teacher_1)}")
print(teacher.name)  # 输出: Susan
print(teacher.age)   # 输出: 33
print(teacher.subject)  # 输出: English
teacher_1.subject = 'Math' #修改属性
print(teacher.subject)  # 输出: Math

在使用__init__初始化时,必须先填入'self',因为self代表的是实例本身(打印内存地址查看):

  • 对同一个类,可以创建不同的实例,每次调用,可以将不同实例作为self参数传入
  • 通过self.属性名self.方法名()获取实例的属性和方法
  • 数据隔离:确保每个实例有独立的数据空间

注意在对类实例化时,传入的参数是初始化方法中的(一些属性)。后续在普通方法中的参数,是在调用函数的时候传入(与之前的普通函数调用相同)。当然,这些参数肯定是除‘self’之外的。

普通方法(自定义)

与Init方法不同,自定义的方法只有手动调用时才会被执行。但相同的时,第一个参数也是'self',原因同上。其他的写法与之前单独的函数写法基本相同,但区别如下:

  • 第一个参数是“self”,后面是正常的参数
  • 需要在函数内部使用类的属性和方法时,必须使用self,比如self.name而不是name
class Teacher:
    # 初始化方法接受参数以动态设置教师的属性
    def __init__(self, name, subject, age):
        self.name = name
        self.subject = subject
        self.age = age
    # 不是init的都叫做普通方法
    # 普通方法,模拟教师上课的行为
    def teach_lesson(self):
        print(f"{self.name}正在教{self.subject}。")
    # 另一个普通方法,模拟教师批评学生的行为
    def criticize(self, student_name):
        print(f"{self.name}正在批评{student_name}。")

# 创建Teacher类的实例
teacher = Teacher("Susan", "English", 33)
# 调用教师的方法
teacher.teach_lesson()
teacher.criticize("John")#普通方法的参可以等到调用该方法的时候再传

关于构造方法与普通方法的对比:

类的继承

类的继承是面向对象编程的重要特性,允许基于已有的类创建新类,而新类会自动获得父类的属性和方法,并可以添加新的功能或修改现有功能。

使用类的继承,实际上很大程度上与之前的函数封装、装饰器类似,就是减少代码重复。比如定义了一个猫类别和狗类别,然后发现它们中存在相同的地方(吃东西、睡觉),完全可以将这些提取出来,使用一个父类(动物)来包含。猫类和狗类只要继承就可以,而对应于别的动物(鱼类、鸟类)也可以适用。

此外,适用类的继承有如下用途:

  • 建立层次关系,更精确地建模现实世界,比如上面的动物——猫/狗/鱼/鸟
  • 扩展和定制功能,在每一个子类中可以重写新增属性或方法作为自身的特色
  • 多态性、便于维护和更新(修改父类可影响所有子类)

在用代码实现时需要注意:

  • 类名后的括号中填入父类名称(可以不只一个)
  • 使用super()调用父类方法:子类初始化或者需要扩展父类方法时使用;完全重写或新增方法时不需要

下面是代码示例:

# 定义一个父类
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def sleep(self):
        print(f'{self.name}在睡觉')
    def speak(self):
        print(f"{self.name} 发出声音")
    
class Dog(Animal): #继承需要在括号中指定父类
    def __init__(self,name,age,color): #传入父类的参数,同时也可以传入自己的参数
        # super()函数 除了在构造方法中使用,还可以在其他方法中使用
        super().__init__(name,age) #调用父类的构造方法,super()是一个内置函数,返回父类的实例
        self.color = color #新增子类特有的属性
    #重写方法,如果子类定义了与父类同名的方法,子类实例会优先调用子类的方法。
    def sleep(self): 
        print(f'{self.color}的{self.name}在睡觉')
    #重写——扩展父类功能
    def speak(self):
        super().speak()  # 先调用父类的方法
        print("汪汪叫")    # 再添加子类的行为
    #新增功能
    def run(self):
        pass

dog = Dog("旺财", 3,'红色')
dog.sleep() 

作业

题目1:定义圆(Circle)类

要求:

  1. 包含属性:半径 radius。
  2. 包含方法:calculate_area():计算圆的面积(公式:πr²)。calculate_circumference():计算圆的周长(公式:2πr)。
  3. 初始化时需传入半径,默认值为 1。
import math
class Circle:
    def __init__(self,radius):
        self.radius = radius
    def calculate_area(self): #计算面积
        area = round(math.pi*pow(self.radius,2),2)
        return area
    def calculate_circumference(self): #计算周长
        circumference = round(2*math.pi*self.radius,2)
        return circumference
#调用
circle = Circle(5)
print(f"半径:{circle.radius}")       # 输出:半径:5
print(f"面积:{circle.calculate_area()}")   # 输出:面积:78.54
print(f"周长:{circle.calculate_circumference()}") # 输出:周长:31.42

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

  1. 包含属性:长 length、宽 width。
  2. 包含方法:calculate_area():计算面积(公式:长×宽)。calculate_perimeter():计算周长(公式:2×(长+宽))。 is_square() 方法,判断是否为正方形(长 == 宽)。
  3. 初始化时需传入长和宽,默认值均为 1。
class Rectangle:
    def __init__(self,length=1,width=1): #长和宽默认为1
        self.length = length
        self.width = width
    def calculate_area(self): #计算面积
        area = self.length * self.width
        return area
    def calculate_perimeter(self): #计算周长
        perimeter = 2*(self.length + self.width)
        return perimeter
    def is_square(self): #判断是否为正方形
        return self.length == self.width
    
rect = Rectangle(4, 6)
print(f"长:{rect.length}, 宽:{rect.width}")  # 输出:长: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.is_square()}")  # 输出:是否为正方形:True

题目3:图形工厂

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

示例:shape_type='circle':创建圆(参数:半径);shape_type='rectangle':创建长方形(参数:长、宽)

import math
# 定义圆类
class Circle:
    def __init__(self,radius):
        self.radius = radius
    def calculate_area(self): #计算面积
        area = round(math.pi*pow(self.radius,2),2)
        return area
    def calculate_circumference(self): #计算周长
        circumference = round(2*math.pi*self.radius,2)
        return circumference
# 定义长方形类
class Rectangle:
    def __init__(self,length=1,width=1): #长和宽默认为1
        self.length = length
        self.width = width
    def calculate_area(self): #计算面积
        area = self.length * self.width
        return area
    def calculate_perimeter(self): #计算周长
        perimeter = 2*(self.length + self.width)
        return perimeter
    def is_square(self): #判断是否为正方形
        return self.length == self.width
# 图形工厂  
def create_shape(shape_type,*args):
    if shape_type.lower() == 'circle':
        return Circle(args[0])
    elif shape_type.lower() == 'rectangle':
        return Rectangle(args[0],args[1])
    else:
        return '抱歉,目前支持创建圆或长方形!'
# 测试
shape1 = create_shape("Circle", 5)
print(shape1.calculate_circumference())  # 输出:31.42

shape2 = create_shape("RecTangle", 3, 4)
print(shape2.is_square())                # 输出:False

shape3 = create_shape('triangle',3,4,5)
print(shape3)                            # 抱歉,目前支持创建圆或长方形!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值