当前位置: 首页 > news >正文

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

目录

1、初识对象

使用对象数据组织:

2、成员方法

类的定义和使用语法

成员方法的使用

3、类和对象

4、构造方法

5、其他内置方法

__str__字符串方法:

__lt__小于符号比较方法:

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

__eq__比较运算符实现方法: 

6、封装

私有成员:

 使用私有成员:

7、继承

继承的基本语法:

复写和使用父类成员:

8、类型注解

变量的类型注解:

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

Union类型:

9、多态



1、初识对象

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

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

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

使用对象数据组织:

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

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

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

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

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

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

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

2、成员方法

类的定义和使用语法

类的使用语法:

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

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

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

创建类对象的语法:

对象=类名称()  

成员方法的使用

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 

注意事项:

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、类和对象

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

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

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__方法使用 

# 构造对象
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语句,完成信息的输出

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__字符串方法:

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__方法,控制类转换为字符串行为。

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__小于符号比较方法:

#__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__方法,即可同时完成:小于符号和大于符号两种比较。

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__小于等于比较符号方法:

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__比较运算符实现方法: 

# __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、封装

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

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

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

私有成员:

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

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

· 私有成员变量

· 私有成员方法

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

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

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

举个例子:

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) # 报错,无法使用

 使用私有成员:

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

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、继承

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

比如:

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):

        类内容体

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 # 用来补全语法

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

复写和使用父类成员:

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

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().成员方法()

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)对代码进行类型推断,协助做代码提示

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

支持:

· 变量的函数注解

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

变量的类型注解:

基础语法:变量:类型 

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:类型

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

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

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 

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

Union类型:

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、用以获得同一行为、不同状态 

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)称之为抽象方法

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 练习:基于TCP协议实现一个网盘系统
  • 在windows下抓空包(monitor网卡+wareshark+MNM)
  • 105页PPT:华为ISC集成供应链变革、模式与方法解析
  • QT如何ui上的QTableWidget控件如何使用
  • 误删文件后的数据救赎实战恢复指南
  • ABB HDS大功率永磁同步伺服电机的创新特性
  • Java stream使用与执行原理
  • 速盾:你知道高防 IP 和高防 CDN 的区别吗?
  • Golang | Leetcode Golang题解之第395题至少有K个重复字符的最长子串
  • 《Python读取 Excel 数据》
  • 美术|基于java+vue的美术外包管理信息系统(源码+数据库+文档)
  • Java数据库连接池的优化与配置
  • 音视频入门基础:AAC专题(1)——AAC官方文档下载
  • Vue(7)——工程化开发
  • 人工智能在网络安全领域的应用探索
  • [nginx文档翻译系列] 控制nginx
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • Druid 在有赞的实践
  • es6
  • Fabric架构演变之路
  • Mac转Windows的拯救指南
  • Mybatis初体验
  • ng6--错误信息小结(持续更新)
  • Octave 入门
  • 初识 beanstalkd
  • 大数据与云计算学习:数据分析(二)
  • 大型网站性能监测、分析与优化常见问题QA
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 番外篇1:在Windows环境下安装JDK
  • 基于组件的设计工作流与界面抽象
  • 你真的知道 == 和 equals 的区别吗?
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 仓管云——企业云erp功能有哪些?
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • #FPGA(基础知识)
  • #Linux(权限管理)
  • #NOIP 2014# day.2 T2 寻找道路
  • #每日一题合集#牛客JZ23-JZ33
  • $.ajax()
  • (7)STL算法之交换赋值
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (独孤九剑)--文件系统
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (七)Activiti-modeler中文支持
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (学习日记)2024.01.09
  • (转)setTimeout 和 setInterval 的区别
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • *算法训练(leetcode)第四十七天 | 并查集理论基础、107. 寻找存在的路径