【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()方法,是空实现。这种设计的含义是:

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

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

相关推荐
胡西风_foxww1 小时前
Java的extends通配符
java·开发语言·通配符·extends
胡萝卜的兔1 小时前
golang -gorm 增删改查操作,事务操作
开发语言·后端·golang
屁股割了还要学1 小时前
快速过一遍Python基础语法
开发语言·python·学习·青少年编程
武当豆豆3 小时前
C++编程学习阶段性总结
开发语言·c++
学不动CV了4 小时前
C语言32个关键字
c语言·开发语言·arm开发·单片机·算法
你怎么知道我是队长4 小时前
python-enumrate函数
开发语言·chrome·python
小屁孩大帅-杨一凡4 小时前
如何解决ThreadLocal内存泄漏问题?
java·开发语言·jvm·算法
大熋4 小时前
Playwright Python 教程:网页自动化
开发语言·python·自动化
赟赟、嵌入式5 小时前
imx6ul Qt运行qml报错This plugin does not support createPlatformOpenGLContext!
开发语言·qt
A7bert7775 小时前
【YOLOv8-obb部署至RK3588】模型训练→转换RKNN→开发板部署
linux·c++·人工智能·python·yolo