【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关键字,尽管在参数列表,但是传参的时候可以忽略它。

# 类定义
class Student:
    # 类属性
    name = None
    age = None

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

stu.test2('666')

构造方法

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

  • 在创建类对象(构造类)的时候,会自动执行。
  • 在创建类对象(构造类)的时候。将传入参数自动传递给__init__()方法使用
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来表示。

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

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__():控制类转换为字符串的行为。

# 类魔术方法
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种比较。

# 类魔术方法
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种比较。

# 类魔术方法
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种比较。

# 类魔术方法
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个下划线)
# 私有成员
class Student:
    __card_no = None

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


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

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

# 私有成员
class Student:
    __card_no = False

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

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

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

继承

单继承基础语法:

class 类名(父类名):
    类内容体

示例:

# 单继承
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类之间支持多继承,多继承基础语法:

class 类名(父类名1, 父类名2, 父类名3, ..., 父类名N):
    类内容体

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

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

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

# 复写
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().成员方法()
# 调用父类方法
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)对代码进行类型推断,协助做代码提示。
  • 帮助开发者自身对变量进行类型注释

支持:

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

为变量设置类型注解

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

# 基础数据类型注解(一般无需注解)
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 函数(方法)名(形参名: 类型, 形参名: 类型, ...)

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

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

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

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

Union联合类型注解

# 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联合类型注解,在变量注解、函数(方法)形参和返回值注解中,均可使用

多态

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

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

即:

  • 以父类做定义声明
  • 以子类做实际工作
  • 用以获得同一行为,不同状态
# 多态
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()方法,是空实现。这种设计的含义是:

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杼蛘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值