@浙大疏锦行
今日任务:
- 类的定义
- pass占位语句
- 类的初始化方法
- 类的普通方法
- 类的继承:属性的继承、方法的继承
类的定义
对类进行定义时,使用class关键字,注意与函数不同,在类名的后面不需要加括号,示例如下:
            
            
              python
              
              
            
          
          class ClassName: #类名通常遵循大驼峰命名法 (UpperCamelCase),即每个单词的首字母都大写
    """类的文档字符串"""
    # 类的内容
    pass #pass 为占位符,避免运行错误关于pass与缩进:
- Python通过缩进定义代码块的结构,对于def,class,if等,如果后续代码块为空,那么就会因为无法确定结构的范围而抛出IndentationError。
- pass 本身不执行任何操作,但它可以起到一个占位置的作用。因此,当需要一个语法上存在的代码块,但又暂时不想在其中放入任何实际的逻辑时,就可以使用pass占位。
在定义一个类时,它可以具有属性和方法两个部分。
- 属性(是什么):用于存储数据,初始化方法构造 、类内部直接定义、类外部添加
- 方法(做什么):定义行为,初始化方法(init)、类方法、静态方法、魔术方法等等
类的方法
上面提到了类的方法和属性,在调用时,对方法和属性分别使用example.method()、example.name。
下面主要说明初始化方法和自定义的普通方法。
初始化方法
init (注意前后均各有两条下划线)属于类的构造方法,当创建对象时,会被自动调用。
关于参数,可以自己使用self.属性名给出默认值 或者赋值给外部传入的参数值。
            
            
              python
              
              
            
          
          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
            
            
              python
              
              
            
          
          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() 调用父类方法:子类初始化 或者需要扩展父类方法时使用;完全重写或新增方法时不需要
下面是代码示例:
            
            
              python
              
              
            
          
          # 定义一个父类
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)类
要求:
- 包含属性:半径 radius。
- 包含方法:calculate_area():计算圆的面积(公式:πr²)。calculate_circumference():计算圆的周长(公式:2πr)。
- 初始化时需传入半径,默认值为 1。
            
            
              python
              
              
            
          
          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)类
- 包含属性:长 length、宽 width。
- 包含方法:calculate_area():计算面积(公式:长×宽)。calculate_perimeter():计算周长(公式:2×(长+宽))。 is_square() 方法,判断是否为正方形(长 == 宽)。
- 初始化时需传入长和宽,默认值均为 1。
            
            
              python
              
              
            
          
          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':创建长方形(参数:长、宽)
            
            
              python
              
              
            
          
          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)                            # 抱歉,目前支持创建圆或长方形!