# 2-面向对象 * 封装 * 继承 * 多态 ## 类的属性和方法 ```python class 类名: 属性 = 属性值 def 方法名(self, 形参1, 行参2, ...): 方法体 对象 = 类名() 对象.方法名() # self 必须填写 # 表示类对象本身 # 在方法内部, 通过self访问属性 # 调用的时候忽略它 ``` 示例 ```python class Student: name = None age = None def say_hello(self): print(f"hello, my name is {self.name}, and my age is {self.age}") stu1 = Student() stu1.name = "张三" stu1.age = 18 stu1.say_hello() print(stu1.name) print(stu1.age) ``` ## 构造方法 ```python # __init__() # 同样需要self参数 # 构造方法的实例化时会自动执行 # 把参数传给构造方法使用 # 属性可以不写, 放到构造方法里声明并赋值 ``` 示例: ```python class Student: def __init__(self, name, age): self.name = name self.age = age print("我是构造方法") def say_hello(self): print(f"hello, my name is {self.name}, and my age is {self.age}") stu1 = Student("张三",18) stu1.say_hello() print(stu1.name) print(stu1.age) ``` ## 常见的内置方法(魔术方法) **都是用`__`包围起来** ### `__str__` 字符串方法 > 返回字符串, 供打印该对象时输出 ```python class Student: def __init__(self, name, age): self.name = name self.age = age print("我是构造方法") def say_hello(self): print(f"hello, my name is {self.name}, and my age is {self.age}") stu1 = Student("张三",18) print(stu1) # 输出内存地址, 类似 <__main__.Student object at 0x10ec4ffd0> ``` ```python class Student2: def __init__(self, name, age): self.name = name self.age = age print("我是构造方法") def say_hello(self): print(f"hello, my name is {self.name}, and my age is {self.age}") def __str__(self): return (f"学生对象, 名称是 {self.name}, 年龄是 {self.age}") # 返回字符串 stu2 = Student2("张三",18) print(stu2) # 学生对象, 名称是 张三, 年龄是 18 ``` ### `__lt__` 小于符号比较 > 让两个实例的对象可以比较 ```python # 传入 self 和 other # 返回True or False class Student: def __init__(self, name, age): self.name = name self.age = age def __lt__(self, other): return self.age < other.age stu1 = Student("张三",18) stu2 = Student("李四",19) print(stu1 < stu2) ``` ### `__le__` 小于等于 符号比较 ```python class Student: def __init__(self, name, age): self.name = name self.age = age def __le__(self, other): return self.age <= other.age stu1 = Student("张三",18) stu2 = Student("李四",19) stu3 = Student("王五",18) print(stu1 <= stu2) print(stu1 >= stu2) print(stu1 <= stu3) print(stu1 >= stu3) ``` ### `__eq__` 等于号 符号比较 ```python class Student: def __init__(self, name, age): self.name = name self.age = age def __eq__(self, other): return self.age == other.age stu1 = Student("张三",18) stu2 = Student("李四",19) stu3 = Student("王五",18) print(stu1 == stu2) print(stu1 == stu3) ``` ## 封装 * 私有属性, 私有方法: 用__开头 > 私有属性和方法只能在类内部使用 ```python class Phone: def __init__(self,voltage): self.__voltage = voltage def __type(self): if self.__voltage > 4: return "性能模式" else: return "省电模式" def get_type(self): print(self.__type()) phone1 = Phone(5) phone1.get_type() # phone1.__type() # 报错 # print(phone1.__voltage) # 报错 phone2 = Phone(3) phone2.get_type() ``` ## 继承 ```python # 单继承 class 子类名(父类): 方法体 # 多继承 class 子类名(父类1, 父类2, ...): 方法体 # 多继承, 属性或者方法名重复的话, 左边的优先 # pass关键字: 占位用的, 没有实际含义 ``` ### 复写 > 同样名称的属性或者方法在子类中再写一遍 ### 子类调用父类的方法 ```python 方法一: 父类名.属性 父类名.方法(self) 方法二: super().属性 super().方法() ``` 示例: ```python class Human: def __init__(self, name, age): self.name = name self.age = age def say_hello(self): print(f"hello, my name is {self.name}, and my age is {self.age}") class Student(Human): def __init__(self, name, age, cla): super().__init__(name, age) # 不需要self # Human.__init__(self, name, age) # 这里要self self.cla = cla def say_hello(self): print(f"hello, my name is {self.name}, and my age is {self.age}, and my class is {self.cla}") stu = Student("张三",18,"一班") stu.say_hello() ``` 子类有多个父类时, 调用父类的init方法, 是调用第一个父类的 ## 类型注解 ### 变量的类型注解 提示性的备注, 错了也不会停止 ```python # 变量: 类型 # 基础类型注解 # 没什么意义, 自动推断 var_int: int = 10 var_float: float = 3.14 var_bool: bool = True var_str: str = "str" # 类对象注解 class Student: pass stu: Student = Student() # 容器类型注解 var_lsit: list = [1, 2, 3] var_tuple: tuple = (1, 2, 3) var_set: set = {1, 2, 3} var_dict: dict = {"name": "张三"} # 容器的详细注解 var_l1: list[int] = [1, 2, 3] # 元组需要把每个元素都标记出来 var_t1: tuple[int, bool, str] = (1, True, "str") var_s1: set[int] = {1,2,3} # 字典需要两个类型, 一个key, 一个value var_d1: dict[str,int] = {"age": 18} ``` ### 在注释中进行类型注解 ```python # type: 类型 name = "张三" # type: str ``` 示例: ```python import random num = random.randint(1, 10) # type: int print(num) ``` ### 函数的类型注解 ```python def 函数名(形参: 类型) -> 返回值类型: pass ``` ### Union 联合类型注解 ```python from typing import Union Union[类型1, 类型2, ...] ``` 示例: ```python from typing import Union my_list: list[Union[str,int]] = [1, "a", 2, "str"] my_dict: dict[str, Union[str,int]] = {"name": "张三", "age": 18} ``` ## 多态 > 同样的函数, 传入不同的对象,能够输出多种状态 * 抽象方法: 方法为空, 只定义, 具体由子类复写 * 抽象类: 具有抽象方法的类, 用于顶层设计