python从入门到精通:面向对象

ops/2024/12/22 23:56:04/

目录

1、初识对象

使用对象数据组织:

2、成员方法

类的定义和使用语法

成员方法的使用

3、类和对象

4、构造方法

5、其他内置方法

__str__字符串方法:

__lt__小于符号比较方法:

__len__小于等于比较符号方法:

__eq__比较运算符实现方法: 

6、封装

私有成员:

 使用私有成员:

7、继承

继承的基本语法:

复写和使用父类成员:

8、类型注解

变量的类型注解:

函数(方法)的类型注解:

Union类型:

9、多态



1、初识对象

在程序中简单使用变量来记录学生信息:

python">student_1 = {"姓名":"小李","性别":"男"}
student_2 = "我叫小刘,今年18,男性"
student_3 = ["小杜","20","男"
]

但使用变量记录数据太乱了,数据组织就会方便不少。

使用对象数据组织:

在程序中是可以做到和生活中那样,设计表格、生产表格、填写表格的组织形式的。

1、在程序中设计表格,我们称之为设计类(class)

python">class Student:name = None # 记录学生姓名

 2、在程序中打印生产表格,我们称之为创建对象

python"># 基于类创建对象
stu_1 = Student()
stu_2 = Student()

3、在程序中填写表格,我们称之为对象属性赋值 

python">stu_1.name = "小李" # 为学生1对象赋予名称属性值
stu_2.name = "小张" # 为学生2对象赋予名称属性值

2、成员方法

类的定义和使用语法

类的使用语法:

class 类名称:class是关键字,表示要定义类了

类的属性:类的属性,即定义在类中的变量(成员变量)

类的行为:类的行为,即定义在类中的函数(成员方法)

创建类对象的语法:

对象=类名称()  

成员方法的使用

python">class Student:name = None # 记录学生姓名age = None # 记录学年龄def say_hi(self):print(f"大家好!,我是{self.name}")
student1 = Student()
student1.say_hi()

可以看出,类中:不仅可以定义属性来记录数据,也可以定义函数,用来记录行为。

其中:类的定义属性(变量),我们称之为成员变量;类中的行为(函数),我们称之为成员方法。 

在类中定义成员方法和定义函数基本一致,但仍有细微区别:

def 方法名(self,形参1,......,形参N):

        方法体 

可以看到,在方法定义的参数列表中,有一个:self关键字

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

· 它用来表示类对象自身的意思

· 当我们使用类对象调用方法时,self会被自动被python传入

· 在方法内部,想要访问类的成员变量,必须使用self 

注意事项:

python">class Student:name = Nonedef say_hi(self):print('Hello World!')def say_hello(self,msg):print(msg)
stu = Student()
stu.say_hi() #调用时无需传参
stu.say_hello("哈哈") # 调用的时候,需要穿msg参数

 因此在传参的时候,self是透明的,可以不必理会。

3、类和对象

现实世界的事物也有属性和行为,类也有属性和行为。使用程序中的类,可有完美地描述现实世界的事物。

之所以创建对象:类只是一种程序内的”设计图纸“,需要基于图纸生产实体(对象),才能正常工作。这种思想,称之为:面向对象编程。

python">class Clock:id = Noneprice = Nonedef ring(self):import winsoundwinsound.Beep(2000,2000)
# 构建2个闹钟对象并使其工作
clock1 = Clock()
clock1.id = "0001"
clock1.price = 100
print(f"闹钟ID:{clock1.id},闹钟价格:{clock1.price}")
clock1.ring()
clock2 = Clock()
clock2.id = "0002"
clock2.price = 50
print(f"闹钟ID:{clock1.id},闹钟价格:{clock1.price}")
clock2.ring()

4、构造方法

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

可以实现:

· 在创建类对象(构造类)的时候,会自动执行.

· 在创建类对象(构造类)的时候,将会传入参数自动传递给__init__方法使用 

python"># 构造对象
class Student:name = None # 可以省略age = None # 可以省略tel = None # 可以省略def __init__(self, name, age, tel):self.name = nameself.age = ageself.tel = telprint("Student类创建了一个对象")
stu = Student("张三",30,"17702119333")

 开学了有一批学生信息需要录入系统,请设计一个类,记录学生的:
姓名、年龄、地址,这3类信息
请实现:
· 通过for循环,配合input输入语句,并使用构造方法,完成学生信息的键盘录入
· 输入完成后,使用print语句,完成信息的输出

python">class Student:def __init__(self, name, age, address):self.name = nameself.age = ageself.address = address
num_student = 10
for i in range(num_student):name = input("请输入学生姓名:")age = input("请输入学生年龄:")address = input("请输入学生地址:")student = Student(name, age, address)print(f"第{i+1}个学生姓名:{student.name},学生年龄:{student.age},学生地址{student.address}")

5、其他内置方法

如__init__构造方法,使python类内置的方法之一。这些内置的类方法,各自有各自特殊的功能,这些内置的方法我们称之为:魔术方法。

__str__字符串方法:

python">class Student:def __init__(self, name, age):self.name = nameself.age = age
student = Student("周周",21)
print(student) #结果:<__main__.Student object at 0x000001A95300EAB0>
print(str(student)) #结果:<__main__.Student object at 0x000001A95300EAB0>

当类对象需要被转换为字符串时,会输出如上结果(内存地址),我们可以通过__str__方法,控制类转换为字符串行为。

python">class Student:def __init__(self, name, age, ):self.name = nameself.age = agedef __str__(self):return f"student name is {self.name}, age is {self.age}"
student = Student("周周",23)
print(student) #运行结果:student name is 周周, age is 23
print(str(student)) #运行结果:student name is 周周, age is 23

__lt__小于符号比较方法:

python">#__lt__小于符号比较方法
class Student:def __init__(self, name, age):self.name = nameself.age = age
stu1 = Student('zhang', 18)
stu2 = Student('zhang', 19)
print(stu1 < stu2) #TypeError: '<' not supported between instances of 'Student' and 'Student'

 直接两个对两个对象进行比较是不可以的,但是在类中实现__lt__方法,即可同时完成:小于符号和大于符号两种比较。

python">class Student:def __init__(self, name, age):self.name = nameself.age = agedef __lt__(self, other):return self.age < other.age # 当前年龄与被比较参数的年龄进行比较
stu1 = Student('zhang', 18)
stu2 = Student('li', 19)
print(stu1 < stu2) # 结果为true
print(stu1 > stu2) # 结果为false

__len__小于等于比较符号方法:

python">class Student:def __init__(self, name, age):self.name = nameself.age = agedef __le__(self, other):return self.age <= other.age # 当前年龄与被比较参数的年龄进行比较
stu1 = Student('zhang', 18)
stu2 = Student('li', 19)
print(stu1 <= stu2) # 结果为true
print(stu1 >= stu2) # 结果为false

__eq__比较运算符实现方法: 

python"># __eq__,比较运算符实现方法
class Student:def __init__(self, name, age):self.name = nameself.age = agedef __eq__(self, other):return self.age == other.age
stu1 = Student('zhang', 18)
stu2 = Student('lisi', 18)
print(stu1 == stu2) # 结果为true

需要注意的是:

1、不使用__eq__比较运算符,对象之间也可以进行比较,但是是比较的地址。也即是:不同对象==比较一定是False的结果

2、使用了__eq__方法,就可以按照自己的想法来决定两个值是否相等了 

6、封装

面向对象编程,是许多编程语言都支持的一种编程思想。简单理解就是:基于模板(类)去创建实体(对象),使用对象完成功能开发。

封装表示的是将现实世界的属性和行为封装到类中,描述为成员变量和成员方法。从而完成程序对现实世界事物的描述。

现实世界中的事物,有属性和行为。但并不代表着这些属性和行为都是开放给用户的。

私有成员:

既然现实事物有不公开的属性和行为,那么作为现实事物在程序中映射的类,也应该支持。

类中提供了私有成员的形式来支持:

· 私有成员变量

· 私有成员方法

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

· 私有成员变量:变量名__开头 

· 私有成员方法:方法名以__开头

举个例子:

python">class  Phone:IMEI = None # 序列号producer = None # 厂商__current_voltage = None #当前电压(私有变量)def call_by_5g(self):print("5g已启用")def __keep_single_core(self): # 私有成员方法print("让CPU以单核模式进行以节省电量")
phone = Phone() #创建对象
phone.__keep_single_core() # 使用私有成员方法(报错)
phone.__current_voltage = 5.0 # 不报错,但无效
print(phone.__current_voltage) # 报错,无法使用

 使用私有成员:

私有成员无法被类对象使用,但是可以被其他的成员使用。

python">class  Phone:__current_voltage = 5 #当前电压(私有变量)def __keep_single_core(self): # 私有成员方法print("让CPU以单核模式进行以节省电量")def call_by_5g(self):if self.__current_voltage >= 1print("5g已启用")else:self.__keep_single_core()print("电量不足,不能启动5G,以自动启动单核节省电量")

实际意义:在类中提供仅内部使用的属性方法方法,而不对外开放(类对象无法使用),起到保护数据的作用,保护代码隐私,设置权限,防止某些属性修改。 

7、继承

继承就是指把已有的东西(类)拿过来进行修改,达到从新进行使用的目的。

比如:

python">class Phone:IMEI = Noneprodecer = Nonedef call_by_4g(self):print("4g通话")
class Phone2022(Phone):face_id = True # 支持面部识别def call_by_5g(self):print("2022最新5g")

继承的基本语法:

class 类名(父类名):

        类内容体

继承分为:单继承和多继承。比如上一个例子就是一个典型的单继承 

继承:将从父类那里继承(复制)来成员变量和成员方法(不含私有)

多继承:python的类之间也支持多继承,即一个类,可以继承多个父类。语法:

class 类名(父类1,父类2,...,父类N):

        类内容体

python">class Phone:IMEI = Noneprodecer = Nonedef call_by_5g(self):print("5g通话")
class NFCReader:nfc_type = "第五代"producer = "小米"def read_card(self):print("读取NFC卡")def wrirte_card(self):print("写入NFC卡")
class RemoteControl:rc_type = "红外遥控"def control(self):print("开启红外遥控")
class MyPhone(Phone, NFCReader, RemoteControl,):pass # 用来补全语法

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

复写和使用父类成员:

复写:子类继承父类的成员属性和成员方法后,如果对其“不满意”,可以进行复写。即:在子类中重新定义同名的属性或方法即可。

python">class Phone:IMEI = Noneproducer = "apple"def call_by_5g(self):print("父类5g通话")
class MyPhone(Phone):producer = "小米"def call_by_5g(self):print("子类的5g通话")

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

方式1:

· 调用父类成员

        使用成员变量:父类名.成员变量

        使用成员方法:父类名.成员方法(self)

方式2:

 · 使用super()调用成员父类

        使用成员变量:super().成员变量

        使用成员方法:super().成员方法()

python">class Phone:IMEI = Noneproducer = "apple"def call_by_5g(self):print("开启5g通话")
class MyPhone(Phone):producer = "小米"def call_by_5g(self):print("开启CPU单核模式,确保通话时省电")# 方式1:Phone.call_by_5g(self)# 方式2:super().call_by_5g()print("关闭CPU单核模式,确保性能")

8、类型注解

我们自定义的模块或者函数等,pycharm是无法通过代码确定应传入什么类型,我们需要使用类型注解。

python在3.5版本之后引入了类型注解,一边方便静态类型检查工具,IDE等第三方工具。

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

主要功能:

· 帮助第三方IDE工具(比如pycharm)对代码进行类型推断,协助做代码提示

· 帮助开发者自身对变量进行类型注解。

支持:

· 变量的函数注解

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

变量的类型注解:

基础语法:变量:类型 

python">var_1:int=10
var_2:float = 3.14
var_3:str = 'python'
# 类对象类型注解
class Student:pass
stu: Student = Student()
# 数据容器类型注解
my_list:list = [1,2,3]
my_dict:dict = {"python":666}
my_set:set = {1,2,3}
my_tuple:tuple = (1,2,3)
# 数据容器类型详细注解
my_list:list[int] = [1,2,3]
my_dict:dict[str,int] = {"python":666}

 注意:元组类型设置详细注解,需要将每个元素都标记出来;字典类型设置类型详细注解,需要两个类型,第一个是key第二个是value。

除了使用变量:类型,这种语法做注解外,也可以在注解中进行类型注解。语法:

# type:类型

python">class Student:pass
var_1 = random.randint(1,10) # type: int
var_2 = json.loads(data) # type: dict[str,int]
var_3 = func() # type: Student

一般,在我们无法看出变量类型之时才会添加变量的类型注解。

python">class Student:pass
var_1: int = random.randomint(1,10)
var_2: dict = json.loads(data)
var_3: Student = Student()

 类型注解的限制在于不会对类型做检验和判断。也就是,类型注解仅仅是提示性的,不是决定性的。比如下方代码是不会报错的:

var_1: int = "python"

var_2: str = 123 

函数(方法)的类型注解:

函数和方法的形参类型注解语法:

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

        pass

返回值注解:

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

        pass 

python">def func(data:list) -> list:return data

Union类型:

python">from typing import Union
my_list:list[Union[str,int]] = [1,2,"python"]
my_dict:dict[str, Union[str, int]] = {"name":"李白","age":23}

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

9、多态

多态指的是多种状态,即完成某个行为时,使用不同的对象得到不同的状态。

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

1、函数(方法)形参声明接受父类对象

2、时机传入的子类对象进行工作

即:

1、以父类做定义声明

2、以子类做实际工作

3、用以获得同一行为、不同状态 

python">class animals:def speak(self):pass
class dog(animals):def speak(self):print("汪汪")
class cat(animals):def speak(self):print("喵喵")
def make_noise(animals: animals):animals.speak()
dog = dog()
cat = cat()
make_noise(dog)
make_noise(cat)

 抽象类(接口)

上述例子中animals的speak方法是空实现,这种设计的含义:

1、父类用来确定有哪些方法

2、具体的方法实现,由子类自行决定

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

抽象类:含有抽象方法得类统称抽象类

抽象方法:方法是空实现的(pass)称之为抽象方法

可以配合多态,完成抽象父类的实现(设计标准)以及具体子类的实现(实现标准)


http://www.ppmy.cn/ops/110390.html

相关文章

Android framework 编程之-根据包名获取应用UID流程分析

1. 获取本地注册的Package 功能的对象 关于本地注册和binder 注册大家可以看看这篇博客 https://blog.csdn.net/u014023550/article/details/113605341 PackageManagerInternal pmInt LocalServices.getService(PackageManagerInternal.class); Package 功能本地对象的注册时…

深度学习-神经网络

文章目录 一、基本组成单元&#xff1a;神经元二、神经网络层三、偏置与权重四、激活函数1.激活函数的作用2.常见的激活函数1).Sigmoid2).Tanh函数3).ReLU函数 五、优点与缺点六、总结 神经网络&#xff08;Neural Network, NN&#xff09;是一种模拟人类大脑工作方式的计算模型…

Vue: 创建vue项目

目录 一.创建项目 二.项目添加 三.添加成功 一.创建项目 打开本机终端输入npm create vuelatest 二.项目添加 1. 项目名称&#xff1a; Project name: one_vue 2.是否添加TypeScript支持&#xff1a;Add TypeScript? Yes 3.是否添加JSX支持&#xff1a;Add JSX Suppor…

Spring 定时任务与 XXL-JOB 灵活切换方案

在使用XXL—JOB的实现定时任务过程中&#xff0c;有时候可能由于部署环境的要求&#xff0c;就只能用Spring自带的实现方式。 所以为了通用性和灵活性&#xff0c;突发奇想地看看能不能实现在不修改原本Spring定时任务代码的前提下&#xff0c;通过配置灵活控制定时任务具体的实…

软件质量保证例题

答案&#xff1a;D 软件质量保证 功能性 适合性 准确性 互操作性 安全保密性 依从性 可靠性 成熟性 容错性 易恢复性 易用性 易理解性 易学性 易操作性 效率 时间特性 资源利用性 维护性 易分析性 易改变性 稳定性 易测试性 可移植性 适应性 易安装性 一致性 易替换…

灯带与线性灯:照明界的双子星,区别与厂家解决方案深度剖析

在现代照明领域&#xff0c;灯带与线性灯作为两种备受欢迎的照明产品&#xff0c;因其独特的设计与应用场景而广受青睐。然而&#xff0c;对于许多消费者乃至设计师而言&#xff0c;二者之间的具体区别以及选择时的考量因素往往令人困惑。本文将从专业角度出发&#xff0c;深入…

visual studio code下载教程(手把手)

今天我来给大家介绍一下visual studio code (VScode)的下载 一、VSCode介绍 VSCode 是一款由微软开发且跨平台的免费源代码编辑器&#xff1b;该软件支持语法高亮、代码自动补全、代码重构、查看定义功能&#xff0c;并且内置了命令行工具和 Git 版本控制系统。 二、官方下载…

嵌入式软件--51单片机 DAY 4

一、蜂鸣器 当电流通过线圈时会产生电磁场&#xff0c;电磁场与永磁体相互作用&#xff0c;从而使金属膜产生震动而发声。为使金属膜持续震动&#xff0c;蜂鸣器需要使用震荡电路进行驱动。有些蜂鸣器元件内部自带震荡驱动电路&#xff0c;这种蜂鸣器叫做有源蜂鸣器&#xff0…