【Python】类和对象

类定义和使用

python 复制代码
# 类定义
class Student:
    # 类属性
    name = None
    age = None

    # 类行为
    def test(self):
        print(f'我是{self.name},今年{self.age}岁。')


# 类调用
stu = Student()
stu.name = 'Aiw'
stu.age = '20'
print(stu)
stu.test()

self关键字是成员方法定义的时候,必须填写的:

  • 它用来表示类对象自身的意思
  • 当使用类对象调用方法的时候,self会自动被python传入
  • 在方法内部,想要访问类的成员变量,必须使用self

self关键字,尽管在参数列表,但是传参的时候可以忽略它。

python 复制代码
# 类定义
class Student:
    # 类属性
    name = None
    age = None

    # 类行为
    def test2(self, msg):
        print(f'新的消息是{msg}')

stu.test2('666')

构造方法

Python类可以使用:init()方法,称之为构造方法。可以实现:

  • 在创建类对象(构造类)的时候,会自动执行。
  • 在创建类对象(构造类)的时候。将传入参数自动传递给__init__()方法使用
python 复制代码
class Student:
    name = None
    age = None

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say_hi(self):
        print(f'我是{self.name},今年{self.age}岁。')	


stu = Student('Aiw', 20)
stu.say_hi()	# 我是Aiw,今年20岁。

在构造方法内定义成员变量,需要使用self关键字,因为变量是定义在构造方法内部,若要成为成员变量,需要用self来表示。

使用构造方法时,类属性可以省略不写

python 复制代码
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say_hi(self):
        print(f'我是{self.name},今年{self.age}岁。')	

stu = Student('Aiw', 20)
stu.say_hi()	# 我是Aiw,今年20岁。

魔术方法

init()构造方法,是Python类内置的方法之一。这些内置的类方法,各自有各自特殊的功能,这些内置方法称为:魔术方法。

str():控制类转换为字符串的行为。

python 复制代码
# 类魔术方法
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"Student[name={self.name},age={self.age}]"


stu = Student('Aiw', 20)
print(stu)  # Student[name=Aiw,age=20]

若不使用__str__()魔术方法,则会输出对象的内存地址

lt():对象比较方法,在类中实现__lt__()方法,即可同时完成:< 和 >2种比较。

python 复制代码
# 类魔术方法
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
	
    def __lt__(self, other):	# other:另一个类对象
        return self.age < other.age

stu1 = Student('Aiw', 20)
stu2 = Student('Tom', 21)
print(stu1 < stu2)  # True
print(stu1 > stu2)  # False

若不使用__lt__()魔术方法,直接比较对象的话则会报错

le():对象比较方法,在类中实现__le__()方法,即可同时完成:<= 和 >=2种比较。

python 复制代码
# 类魔术方法
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __le__(self, other):    # other:另一个类对象
        return self.age <= other.age

stu1 = Student('Aiw', 20)
stu2 = Student('Tom', 21)
print(stu1 <= stu2)  # True
print(stu1 >= stu2)  # False

eq():对象比较方法,在类中实现__le__()方法,即可同时完成:== 1种比较。

python 复制代码
# 类魔术方法
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, other):    # other:另一个类对象
        return self.age == other.age

stu1 = Student('Aiw', 20)
stu2 = Student('Tom', 20)
print(stu1 == stu2)  # True

不实现__eq__()方法,对象之间也可以比较,但是是比较内存地址,不同对象使用==来比较一定是False

封装

类中提够了私有成员的形式来支持。

  • 私有成员变量
  • 私有成员方法

定义私有成员的方式非常简单,只需要:

  • 私有成员变量:变量名以__开通(2个下划线)
  • 私有成员方法:方法名以__开通(2个下划线)
python 复制代码
# 私有成员
class Student:
    __card_no = None

    def __test(self):
        print('私有方法,无法直接调用')


stu = Student()
print(stu.__card_no)    # 获取私有变量(报错,无法获取)
print(stu.__test())     # 使用私有方法(报错,无法使用)

私有成员无法被类对象使用,但是可以被类中其它成员使用

python 复制代码
# 私有成员
class Student:
    __card_no = False

    def __test(self):
        print('私有方法,无法直接调用')

    def call(self):
        if self.__card_no:
            print('正确')
        else:
            self.__test()

stu = Student()
stu.call()  # 私有方法,无法直接调用

继承

单继承基础语法:

python 复制代码
class 类名(父类名):
    类内容体

示例:

python 复制代码
# 单继承
class Phone:
    IMEI = None  # 序列号
    producer = 'HM'  # 厂商

    def call_4g(self):
        print('4G通话')


class Phone2023(Phone):
    face_id = '435003'  # 面部识别ID

    def call_5g(self):
        print('5G通话')

phone = Phone2023()
print(phone.IMEI)
print(phone.face_id)
print(phone.call_4g())
print(phone.call_5g())

Python类之间支持多继承,多继承基础语法:

python 复制代码
class 类名(父类名1, 父类名2, 父类名3, ..., 父类名N):
    类内容体

多继承注意事项:多个父类中,如果有同名的成员,那么默认以继承的顺序(从左到右)为优先级。

即:先继承的保留,后继承的被覆盖

复写:在子类中重新定义同名的属性或方法即可。

python 复制代码
# 复写
class Phone:
    IMEI = None  # 序列号

    def call_4g(self):
        print('父类的4G通话')


class MyPhone(Phone):
    IMEI = 'test'  # 复写父类属性

    def call_4g(self):  # 复写父类方法
        print('子类的4G通话')

phone = MyPhone()
print(phone.IMEI)   # test
phone.call_4g()     # 子类的4G通话

调用父类同名成员:一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员;如果需要使用被复写的父类的成员,需要特殊的调用方式:

  • 调用父类成员:
    • 使用成员变量:父类名.成员变量super().成员变量
    • 使用成员方法:父类名.成员方法(self)super().成员方法()
python 复制代码
# 调用父类方法
class Phone:
    IMEI = None  # 序列号

    def call_4g(self):
        print('父类的4G通话')


class MyPhone(Phone):
    IMEI = 'test'  # 复写父类属性

    def call_4g(self):  # 复写父类方法
        # 方式1调用父类成员
        print(f'父类的序列号是{Phone.IMEI}')
        # 方式2调用父类成员
        print(f'父类的序列号是{super().IMEI}')

        print('子类的4G通话')

类型注解

Python在3.5版本的时候引入了类型注解,以方便静态类型检查工具,IDE等第三方工具。

类型注解:在代码中涉及数据交互的地方,提供数据类型的注解(显式的说明)。

主要功能:

  • 帮助第三方IDE工具(如PyCharm)对代码进行类型推断,协助做代码提示。
  • 帮助开发者自身对变量进行类型注释

支持:

  • 变量的类型注解
  • 函数(方法)形参列表和返回值的类型注解

为变量设置类型注解

基础语法:变量: 类型 = 值

python 复制代码
# 基础数据类型注解(一般无需注解)
var_1: int = 10
var_2: str = 'hello'
var_3: bool = True
var_4: float = 3.1415926

# 类对象类型注解(一般无需注解)
class Student:
    pass

stu: Student = Student()

# 基础容器类型注解
my_list: list = [1, 2, 3]
my_tuple: tuple = (1, 2, 3)
my_set: set = {1, 2, 3}
my_dict: dict = {"age": 20}

# 基础容器详细类型注解
my_list: list[int] = [1, 2, 3]
my_tuple: tuple[str, bool, int] = ("Aiw", True, 666)
my_set: set[int] = {1, 2, 3}
my_dict: dict[str, int] = {"age": 20}
  • 元组类型设置类型详细注解,需要将每一个元素都标记出来
  • 字典类型设置类型详细注解,需要2个类型,第一个是key,第二个是value
  • 一般无法直接看出变量类型之时会添加变量的注解
  • 类型注解仅仅只是个备注,哪怕标记错了,也不影响程序的运行

为函数(方法)形参设置类型注解

基础语法:def 函数(方法)名(形参名: 类型, 形参名: 类型, ...)

python 复制代码
# 函数(方法)形参类型注解
def add(x: int, y: int):
    return x + y

为函数(方法)返回值设置类型注解

基础语法:def 函数(方法)名(形参名: 类型, 形参名: 类型, ...) -> 返回值类型

python 复制代码
# 函数(方法)形参类型注解
def add(x: int, y: int) -> int:
    return x + y

Union联合类型注解

python 复制代码
# Union联合注解
from typing import Union

my_list: list[Union[str, int]] = [1, 2, 'Aiw']
my_dict: dict[str, Union[str, int]] = {'name': '周杰伦', 'age': 33}

def fn(data: Union[int, str, list]) -> Union[int, str, list]:
    pass

Union联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用

多态

多态常作用在继承关系上,比如:

  • 函数(方法)形参声明接收父类对象
  • 实际传入父类的子类对象进行工作

即:

  • 以父类做定义声明
  • 以子类做实际工作
  • 用以获得同一行为,不同状态
python 复制代码
# 多态
class Animal:
    def seek(self):
        pass

class Dog(Animal):
    def seek(self):
        print('汪汪汪')

class Cat(Animal):
    def seek(self):
        print('喵喵喵')

# 行为函数
def make_noise(animal: Animal) -> None:
    animal.seek()

dog = Dog()
cat = Cat()

make_noise(dog) # 汪汪汪
make_noise(cat) # 喵喵喵

父类Animal的seek()方法,是空实现。这种设计的含义是:

  • 父类用来确定有哪些方法
  • 具体的方法实现,由子类自行决定

这种写法,就叫做抽象类(也可以称之为接口)

相关推荐
数据智能老司机5 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机6 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机6 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机6 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i7 小时前
drf初步梳理
python·django
每日AI新事件7 小时前
python的异步函数
python
这里有鱼汤8 小时前
miniQMT下载历史行情数据太慢怎么办?一招提速10倍!
前端·python
databook17 小时前
Manim实现脉冲闪烁特效
后端·python·动效
程序设计实验室17 小时前
2025年了,在 Django 之外,Python Web 框架还能怎么选?
python
倔强青铜三19 小时前
苦练Python第46天:文件写入与上下文管理器
人工智能·python·面试