个人可否建立网站,启东市住房城乡建设局网站,网站规划内容方案,江门市做网站文章目录 一、面向对象与面向过程1、什么是面向过程#xff1f;2、什么是面向对象#xff1f; 二、类与对象1. 初识对象2. 类的成员方法2.1 类的定义和使用2.2 成员方法 3. 类和对象4. 魔法方法1. _ _ inint _ _ 构造方法2. _ _ str _ _ 字符串方法3. _ _ lt _ _ 小于符号比较… 文章目录 一、面向对象与面向过程1、什么是面向过程2、什么是面向对象 二、类与对象1. 初识对象2. 类的成员方法2.1 类的定义和使用2.2 成员方法 3. 类和对象4. 魔法方法1. _ _ inint _ _ 构造方法2. _ _ str _ _ 字符串方法3. _ _ lt _ _ 小于符号比较方法4. _ _ le _ _ 小于等于比较符号方法5. _ _ eq _ _ 相等比较方法 三、面向对象的三大特征封装、继承、多态1. 封装2. 继承3. 多态 四、类型注解1. 变量的类型注解2. 基础容器类型注解3. 类对象类型注解4. 函数形参和返回值的类型注解5. Union类型联合类型注解 一、面向对象与面向过程
面向对象编程Object-Oriented Programming简称OOP和面向过程编程Procedural Programming简称PP是两种不同的编程范式。
面向对象编程强调把问题分解成对象通过封装、继承和多态等机制来处理对象之间的关系。每个对象都可以独立地处理自己的数据和行为而不需要依赖其他对象。面向对象编程更加注重代码的重用性、可维护性和可扩展性适用于大型、复杂的软件系统开发。
而面向过程编程则是一种以过程为中心的编程方式它将问题分解成一系列的步骤然后按照顺序执行这些步骤以达到求解问题的目的。在面向过程编程中数据和操作是分离的函数是处理数据的主要手段。面向过程编程更加注重效率和速度适用于小型、简单的程序或者性能要求较高的场景。
1、什么是面向过程
面向过程问题分解成一系列的步骤然后按照顺序执行这些步骤 举个简单的例子 相信大家都被问过这样一个问题: 把大象装入冰箱需要几步 按照面向过程的思想需要三步 第一步打开冰箱 第二步把大象塞进去 第三步关上冰箱 从这里就可以看出面向过程就是把一件事按步骤一步一步来实现
代码实现
# 第一步打开冰箱门
def open_door():print(打开冰箱门)# 第二步把大象放进去
def put_elephant():print(把大象放进去)# 第三步关闭冰箱门
def close_door():print(关闭冰箱门)# 完成三个步骤
def put_elephant_in_fridge():open_door()put_elephant()close_door()# 测试程序
put_elephant_in_fridge()这就是面向过程代码的具体实现啦
2、什么是面向对象
对象就是对问题中的事物的抽象 对象可以说是对现实事物的一种抽象映射。 面向对象就是把现实中的事物都抽象为“对象”。每个对象是唯一的且都可以拥有它的属性与行为。我们就可以通过调用这些对象的方法、属性去解决问题。
按照面向对象的思想 在这个例子中 我们可以把大象看作一个对象冰箱看作一个对象。 冰箱的一些功能开门、装物体、关门
class Elephant: # 大象类def Eat(self): # 吃print(吃)class Fridge: # 冰箱类def open_door(self): # 打开冰箱门print(打开冰箱门)def Put_In(self): # 放入东西print(放入东西)def close_door(self): # 关闭冰箱门print(关闭冰箱门)在面向对象中每个对象是独立的有属于它自己的功能只需要专心实现自己的功能就好。所以在建立对象模型阶段仅仅关注对象有什么的功能但不考虑如何实现这些功能。
面向对象对象的特点有很好的延展性比如我给大象赋予了一个吃的功能它通过调用就可以在冰箱里去吃东西。面向对象就是把现实问题抽象为对象通过调用每个对象的属性或功能去解决问题。
二、类与对象
1. 初识对象
什么是对象 对象是面向对象编程中的一个概念它是类的一个实例化即具体化的结果。对象是具体的、实际存在的可以在程序中被创建、操作和销毁。 面向对象编程中对象是由属性 和方法组成的。属性表示对象的状态和特征方法表示对象可以执行的操作和行为。 每个对象都属于某个类类是对象的抽象它定义了对象所具有的属性和方法的结构和行为。对象通过实例化类来创建并且可以根据类的定义进行属性和方法的访问和调用。
以下是一个简单的示例:
class Person:def __init__(self, name, age):self.name nameself.age agedef say_hello(self):print(fHello, 我叫 {self.name}.)# 创建两个Person对象
person1 Person(张三, 25)
person2 Person(李四, 30)# 调用对象的方法
person1.say_hello() # 输出: Hello, 我叫张三.
person2.say_hello() # 输出: Hello, 我叫李四.通过创建对象我们可以根据类的定义来操作和管理数据并执行对象所具有的行为。
2. 类的成员方法
2.1 类的定义和使用
在python中用关键字class来定义类
# 定义一个带有成员方法的类
class Student:# 成员变量name None # 学生的姓名# 定义方法def say_hi1(self):print(f大家好我叫{self.name}) # 成员方法中访问成员变量必须要用self关键字def say_hi2(self, msg):print(f大家好我是{self.name},{msg}) # msg为外部传入的不需要用selfstu1 Student()
stu1.name 张三
stu1.say_hi1()
stu2 Student()
stu2.name 李四
stu2.say_hi2(请多多关照)运行结果 可以看出在类中 不仅可以定义属性用来记录数据也可以定义函数用来记录行为 其中 类中定义的属性变量我们称之为成员变量类中定义的行为函数我们称之为成员方法 2.2 成员方法
语法 在类中定义成员方法和定义函数基本一致只存在细微区别 注意self关键字是成员方法定义的时候必须填写的。 它用来表示类对象自身的意思当我们使用类对象调用方法的是self会自动被python传入self出现在形参列表中但是不占用参数位置无需理会在方法内部想要访问类的成员变量必须使用self 例如
class Student:# 成员变量name None # 学生的姓名# 定义方法def say_hi(self):print(f大家好我叫{self.name})class Student:# 成员变量name None # 学生的姓名def say_hi(self, msg):print(f大家好{msg}) # msg为外部传入的不需要用selfstu Student()
stu.say_hi(请多多关照)可以看到在传入参数的时候没有传入self但也没有报错。
3. 类和对象
基于类创建对象的语法
对象名 类名称()为什么非要创建对象才能使用呢 类只是一种程序内的“设计图纸”或者摸具需要基于图纸或摸具生产实体对象才能正常工作这种套路称之为面向对象编程 举一个简单的例子 类就相当于是闹钟的设计图纸而对象就相当于按照闹钟的设计图纸所生产出来的闹钟。 从上面可以看出设计出来的类包含编号和价格具有响铃的功能。而基于类所创建的对象也有对应的编号和价格 所以面向对象编程就是设计类基于类创建对象由对象做具体的工作。
4. 魔法方法
内置的类方法各自有各自特殊的功能这些内置方法我们称之为魔术方法 常见的魔法方法
魔法方法描述_ _ init _ _(self, …)初始化方法用于初始化对象的属性在对象创建时调用。_ _ str _ _(self)将对象转换为字符串的方法可以通过str(obj)或print(obj)来触发返回对象的可读性好的字符串表示。_ _ repr _ _(self)将对象转换为供解释器读取的形式的字符串通常用于调试和开发可以通过repr(obj)来触发。_ _ len _ _(self)返回对象的长度可以通过len(obj)来调用。_ _ getitem _ _(self, key)获取对象的索引值用于支持索引操作如obj[key]。_ _ setitem _ _(self, key, value)设置对象的索引值用于支持赋值操作如obj[key] value。_ _ delitem _ _(self, key)删除对象的索引值用于支持删除操作如del obj[key]。_ _ iter _ _(self)返回一个迭代器用于支持对象的迭代功能如在for循环中使用。_ _ next _ _(self)用于迭代器返回迭代对象的下一个元素。_ _ eq _ _(self, other)定义对象相等的比较方式通常用于操作符的比较。_ _ lt _ _(self, other)定义对象小于的比较方式通常用于操作符的比较。_ _ add _ _(self, other)定义对象相加的方式通常用于操作符的运算。_ _ sub _ _(self, other)定义对象相减的方式通常用于-操作符的运算。_ _ mul _ _(self, other)定义对象相乘的方式通常用于*操作符的运算。_ _ div _ _(self, other)定义对象相除的方式通常用于/操作符的运算。
上述表格因为语法限制把下面的下划线之间都空了一格实际上两条下划线之间并没有空格
常见的魔法方法
1. _ _ inint _ _ 构造方法
class Student:name None # 姓名age None # 年龄tel None # 手机号stu1 Student()
stu1.name 张三
stu1.age 18
stu1.tel 1686400001
stu2 Student()
stu2.name 李四
stu2.age 19
stu2.tel 163200002上面代码中为对象的属性赋值需要依次进行略显繁琐。可不可以像函数传参那样直接一次性对属性进行赋值呢 答案是肯定的需要使用构造方法_ _ init _ _()
Python类可以使用_ _ init _ _() 方法称之为构造方法。 可以实现 在创建类对象构造类的时候会自动执行。在创建类对象构造类的时候将传入参数自动传递给__init__方法使用。 class Student:# 成员对象__init__构造方法里对成员变量进行了声明并赋值所以成员对象这里可省略name Noneage Nonetel Nonedef __init__(self, name, age, tel):self.name nameself.age ageself.tel telprint(Student类创建了一个类对象) # 输出Student类创建了一个类对象stu1 Student(张三, 18, 13066660)
print(stu1.name) # 输出张三
print(stu1.age) # 输出18
print(stu1.tel) # 输出13066660注意 在构造方法内定义成员变量需要使用self关键字 这是因为变量是定义在构造方法内部如果要成为成员变量需要用self来表示。
2. _ _ str _ _ 字符串方法 方法名_ _ str _ _返回值字符串内容自行定义 class Student:def __init__(self, name, age):self.name nameself.age agestu1 Student(张三, 18)
print(stu1) # 输出__main__.Student object at 0x000001EDFFB09FD0
print(str(stu1)) # 输出__main__.Student object at 0x000001EDFFB09FD0当类对象需要被转换为字符串之时会输出如上结果内存地址
内存地址没有多大作用我们可以通过 _ _ str _ _ 方法控制类转换为字符串的行为。
class Student:def __init__(self, name, age):self.name nameself.age agedef __str__(self):return fname:{self.name}, age:{self.age}stu1 Student(张三, 18)
print(stu1) # 输出name:张三, age:18
print(str(stu1)) # 输出name:张三, age:183. _ _ lt _ _ 小于符号比较方法 方法名_ _ lt _ _传入参数other另一个类对象返回值True 或 False内容自行定义 class Student:def __init__(self, name, age):self.name nameself.age agestu1 Student(张三, 18)
stu2 Student(李四, 19)
print(stu1 stu2)
print(stu1 stu2)像这样直接对2个对象进行比较是不可以的 在类中实现 _ _ lt _ _ 方法可同时完成小于符号和大于符号2种比较。 方法名_ _ lt _ _传入参数other另一个类对象返回值True 或 False内容自行定义 class Student:def __init__(self, name, age):self.name nameself.age age# __lt__魔法方法: 两个类对象进行大于或小于的比较def __lt__(self, other):return self.age other.agestu1 Student(张三, 18)
stu2 Student(李四, 19)
print(stu1 stu2) # 输出True
print(stu1 stu2) # 输出False比较大于符号的魔术方法是_ _ gt _ _, 方法和 _ _ lt _ _ 一样所以实现了 _ _ lt _ _ _ _gt _ _ 就没必要实现了。
4. _ _ le _ _ 小于等于比较符号方法
这个和 _ _ lt _ _ 一样唯一不同的是 _ _ lt _ _ 是比较大于或小于而 _ _ le _ _ 则是比较大于等于和小于等于。 方法名_ _ le _ _传入参数other另一个类对象返回值True 或 False内容自行定义 class Student:def __init__(self, name, age):self.name nameself.age age# __lt__魔法方法: 两个类对象进行大于或小于的比较def __lt__(self, other):return self.age other.agestu1 Student(张三, 18)
stu2 Student(李四, 19)
print(stu1 stu2)
print(stu1 stu2)class Student:def __init__(self, name, age):self.name nameself.age age# __lt__魔法方法: 两个类对象进行大于或小于的比较def __lt__(self, other):return self.age other.age# __le__魔法方法: 两个类对象进行大于等于或小于等于的比较def __le__(self, other):return self.age other.agestu1 Student(张三, 18)
stu2 Student(李四, 19)
print(stu1 stu2) # 输出True
print(stu1 stu2) # 输出False5. _ _ eq _ _ 相等比较方法 方法名eq传入参数other另一个类对象返回值True 或 False内容自行定义 class Student:def __init__(self, name, age):self.name nameself.age age
stu1 Student(张三, 18)
stu2 Student(李四, 19)
print(stu1 stu2) # 输出False不实现 _ _ eq _ _ 方法对象之间也可以进行比较但是是比较内存地址也即是不同对象比较一定是False结果。
class Student:def __init__(self, name, age):self.name nameself.age age# __eq__魔法方法: 两个类对象进行相等的比较def __eq__(self, other):return self.age other.age
stu1 Student(张三, 18)
stu2 Student(李四, 18)
print(stu1 stu2) # 输出True实现了 _ _ eq _ _ 方法就可以按照自己的想法来决定2个对象是否相等了。
三、面向对象的三大特征封装、继承、多态
1. 封装
封装Encapsulation将数据和操作封装在对象中使其成为一个独立的实体外界只能通过对象提供的接口访问和操作内部数据。 对用户隐藏的属性和行为 现实世界中的事物有属性和行为。但是不代表这些属性和行为都是开放给用户使用的。
私有成员 既然现实事物有不公开的属性和行为那么作为现实事物在程序中映射的类也应该支持。
类中提供了私有成员的形式来支持。 私有成员变量私有成员方法 定义私有成员的方式非常简单只需要 私有成员变量变量名以__开头2个下划线私有成员方法方法名以__开头2个下划线 class Phone:IMEI None # 序列号producer None # 厂商# 私有成员变量__current_voltage None # 当前电压def call_by_5g(self):print(5g通话已开启)# 私有成员方法def __keep_5g(self):print(保持5g)私有方法无法直接被类对象使用
phone Phone()
phone.__keep_5g()使用私有成员
class Phone:# 构造方法def __init__(self, __is_5g_enable):# 设置私有变量self.__is_5g_enable __is_5g_enable# 设置私有方法def __check_5g(self):if self.__is_5g_enable True: # 类内部访问私有成员要用selfprint(5G开启)else:print(5G关闭使用4G网络)def call_by_5g(self):self.__check_5g()print(正在通话中...)phone Phone(False)
phone.call_by_5g()2. 继承
继承Inheritance继承允许一个类子类继承另一个类父类的属性和方法子类可以重用父类的代码并且可以在不修改原有代码的情况下进行扩展和修改。 简单来说就是一个类继承另外一个类的成员变量和成员方法
举个简单的例子 手机的更新换代并不是完完全全重新开始而是在原先的基础上新添一些属性和功能。 类比到程序中我们也可以在已经设计好的类上进行更新和修改这就会用到继承。
继承分为单继承和多继承
单继承语法
class 类名(父类):类内容体# 单继承演示
# 定义父类
class Phone:IMEI None # 序列号producer APPLE # 厂商def call_by_4g(self):print(4g通话)# 定义子类
class Phone2022(Phone):face_id 10001def call_by_5g(self):print(5g通话)phone Phone2022()
phone.call_by_4g() # 输出4g通话
print(phone.producer) # 输出APPLE
phone.call_by_5g() # 输出5g通话
print(phone.face_id) # 输出10001通过继承可以将从父类那里继承复制来成员变量和成员方法不含私有给子类使用。
多继承语法 Python的类之间也支持多继承即一个类可以继承多个父类
class 类名(父类1, 父类2, 父类3, ... , 父类N):类内容体举例
# 多继承演示
# 定义父类
class Phone:IMEI None # 序列号producer HM # 厂商def call_by_4g(self):print(4g通话)class NFCReader:nfc_type 第五代producer HMdef read_card(self):print(读取NFC卡)def write_card(self):print(写入NFC卡)class RemoteControl:rc_type 红外遥控def control(self):print(红外遥控开启)# 定义子类
class MyPhone(Phone, NFCReader, RemoteControl):passphone MyPhone()
print(phone.producer) # 输出HM
print(phone.nfc_type) # 输出第五代
phone.read_card() # 输出读取NFC卡
phone.call_by_4g() # 输出4g通话
phone.control() # 输出红外遥控开启多继承注意事项多个父类中如果有同名的成员那么**默认以继承顺序从左到右**为优先级。即先继承的保留后继承的被覆盖。
pass语句 pass是占位语句用来保证函数方法或类定义的完整性表示无内容空的意思。
复写 子类继承父类的成员属性和成员方法后如果对其“不满意”那么可以进行复写。 即在子类中重新定义同名的属性或方法即可。
# 定义父类
class Phone:IMEI None # 序列号producer APPLE # 厂商def call_by_4g(self):print(4g通话)# 定义子类
class MyPhone(Phone):producer HUAWEI # 复写父类属性def call_by_4g(self): # 复写父类方法print(可用5g通话)phone MyPhone()
print(phone.producer) # 输出HUAWEI
phone.call_by_4g() # 输出可用5g通话调用父类同名成员 一旦复写父类成员那么类对象调用成员的时候就会调用复写后的新成员 如果需要使用被复写的父类的成员需要特殊的调用方式: 方式一 调用父类成员 使用成员变量父类名.成员变量 使用成员方法父类名.成员方法(self) 方式二 使用super()调用父类成员 使用成员变量super().成员变量 使用成员方法super().成员方法() 注意只能在子类内调用父类的同名成员。子类的类对象直接调用会调用子类复写的成员
# 定义父类
class Phone:IMEI None # 序列号producer APPLE # 厂商def call_by_4g(self):print(4g通话)# 定义子类
class MyPhone(Phone):producer HUAWEI # 复写父类属性def call_by_4g(self): # 复写父类方法print(可用5g通话)# 调用父类属性和方法# 方法一# print(f调用父类属性[1]:{Phone.producer}) # 调用父类属性# Phone.call_by_4g(self) # 调用父类方法# 方法二print(f调用父类属性[2]:{super().producer}) # 调用父类属性super().call_by_4g() # 调用父类方法phone MyPhone()
print(phone.producer)
phone.call_by_4g()3. 多态
多态Polymorphism多态使得对象可以根据上下文表现出不同的行为同一个方法可以在不同对象上有不同的实现。这样可以提高代码的灵活性和可复用性。 也就是说多种状态即完成某个行为时使用不同的对象会得到不同的状态。
如何理解 同样的行为函数传入不同的对象得到不同的状态 多态常作用在继承关系上。 比如 函数(方法)形参声明接收父类对象实际传入父类的子类对象进行工作 即: 以父类做定义声明以子类做实际工作用以获得同一行为, 不同状态 抽象类接口 抽象类含有抽象方法的类称之为抽象类 抽象方法方法体是空实现的pass 称之为抽象方法
举例
# 抽象类
# 定义父类
class AC:def cool_wind(self):制冷passdef hot_wind(self):制热passdef swing_l_r(self):左右摆风passclass Midea_AC(AC):def cool_wind(self):print(美的空调制冷)def hot_wind(self):print(美的空调制热)def swing_l_r(self):print(美的空调左右摆风)class GREE_AC(AC):def cool_wind(self):print(格力空调制冷)def hot_wind(self):print(格力空调制热)def swing_l_r(self):print(格力空调左右摆风)def cool_wind(ac: AC):ac.cool_wind()# 创建对象
midea Midea_AC()
gree GREE_AC()
cool_wind(midea) # 输出美的空调制冷
cool_wind(gree) # 输出格力空调制冷四、类型注解
在PyCharm中编写代码我们经常能够见到如下提示 为什么PyCharm工具能够做到这一点 因为PyCharm确定这个对象是list类型 同样我们换一份代码定义一个函数func接收一个参数data你会发现PyCharm不会在做出任何提示了 为什么PyCharm工具无法提示了 这是因为PyCharm不确定这个对象是什么类型 PyCharm无法通过代码确定应传入什么类型我们需要使用类型注解
1. 变量的类型注解
基础语法 变量: 类型 为变量设置注解显示的变量定义一般无需注解
# 变量的类型注
var1: int 10
var2: str 张三
var3: bool True像上面这样就算不写注解也明确的知晓变量的类型
2. 基础容器类型注解
# 基础容器类型注解
my_list: list [1, 2, 3]
my_tuple: tuple (1, 2, 3)
my_dict: dict {name: 张三}# 容器类型详细注解
my_list1: list[int] [1, 2, 3]
my_tuple1: tuple[int, str, bool] (1, 张三, True)
my_dict1: dict[str, str] {name: 张三}注意 元组类型设置类型详细注解需要将每一个元素都标记出来字典类型设置类型详细注解需要2个类型第一个是key第二个是value 3. 类对象类型注解
# 类对象类型注解
class Student:passstu: Student Student()4. 函数形参和返回值的类型注解
函数和方法的形参类型注解语法
def 函数名(形参1: 类型, 形参2: 类型, ..., 形参n: 类型):pass# 函数形参的类型注解
def add(x: int, y: int):return x y返回值注解 语法
def 函数名(形参1: 类型, 形参2: 类型, ..., 形参n: 类型) - 返回值类型:pass# 函数形参和返回值的类型注解
def fnuc(data: list) - list:return data除了使用 变量: 类型 这种语法做注解外也可以在注释中进行类型注解。
语法# type: 类型
# 在注释中进行类型注解
var_1: random.randint(1, 10) # type: int
var_2: json.loads({name: 张三}) # type: dict5. Union类型联合类型注解
Union 类型用于指定一个变量可以是多种类型中的一种。 Union联合类型注解在变量注解、函数方法形参和返回值注解中均可使用。
Union的使用方式 导包from typing import Union 语法Union[类型, …, 类型]
# 使用Union类型必须先导包
from typing import Unionmy_list: list[Union[int, str, dict]] [1, 2, name, {age: 18}]
my_dict: dict[str, Union[int, str, list]] {name: 张三, age: 18, grade: [98, 97]}
my_list1: list[Union[int, str, dict[Union[str, int]]]] [1, 2, name, {age: 18}]# 函数的Union类型
def func(data: Union[int, str]) - Union[int, str]:return data