342 lines
6.0 KiB
Markdown
342 lines
6.0 KiB
Markdown
# 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}
|
|
```
|
|
|
|
## 多态
|
|
|
|
> 同样的函数, 传入不同的对象,能够输出多种状态
|
|
|
|
* 抽象方法: 方法为空, 只定义, 具体由子类复写
|
|
* 抽象类: 具有抽象方法的类, 用于顶层设计 |