devStandard/docs/learning/9-python/2-面向对象.md
2025-03-29 14:35:49 +08:00

6.0 KiB

2-面向对象

  • 封装
  • 继承
  • 多态

类的属性和方法

class 类名:
  属性 = 属性值
  def 方法名(self, 形参1, 行参2, ...):
    方法体

对象 = 类名()
对象.方法名()

# self 必须填写
# 表示类对象本身
# 在方法内部, 通过self访问属性
# 调用的时候忽略它

示例

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)

构造方法

# __init__()
# 同样需要self参数
# 构造方法的实例化时会自动执行
# 把参数传给构造方法使用
# 属性可以不写, 放到构造方法里声明并赋值   

示例:

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__ 字符串方法

返回字符串, 供打印该对象时输出

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>
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__ 小于符号比较

让两个实例的对象可以比较

# 传入 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__ 小于等于 符号比较

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__ 等于号 符号比较

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)

封装

  • 私有属性, 私有方法: 用__开头

私有属性和方法只能在类内部使用

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()

继承

# 单继承
class 子类名(父类):
  方法体

# 多继承
class 子类名(父类1, 父类2, ...):
  方法体

# 多继承, 属性或者方法名重复的话, 左边的优先

# pass关键字: 占位用的, 没有实际含义

复写

同样名称的属性或者方法在子类中再写一遍

子类调用父类的方法

方法一:
父类名.属性
父类名.方法(self)

方法二:
super().属性
super().方法()

示例:

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方法, 是调用第一个父类的

类型注解

变量的类型注解

提示性的备注, 错了也不会停止

# 变量: 类型

# 基础类型注解
# 没什么意义, 自动推断

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}

在注释中进行类型注解

# type: 类型

name = "张三" # type: str

示例:

import random

num = random.randint(1, 10) # type: int
print(num)

函数的类型注解

def 函数名(形参: 类型) -> 返回值类型:
  pass

Union 联合类型注解

from typing import Union

Union[类型1, 类型2, ...]

示例:

from typing import Union

my_list: list[Union[str,int]] = [1, "a", 2, "str"]

my_dict: dict[str, Union[str,int]] = {"name": "张三", "age": 18}

多态

同样的函数, 传入不同的对象,能够输出多种状态

  • 抽象方法: 方法为空, 只定义, 具体由子类复写
  • 抽象类: 具有抽象方法的类, 用于顶层设计