高级教程类
给大家安利一个免费且实用的 Python 刷题(面经大全)网站,👉点击跳转到网站。
类是用户定义的蓝图或原型,从中创建对象。类提供了一种将数据和功能捆绑在一起的方法。创建一个新类会创建一种新类型的对象,允许创建该类型的新实例。每个类实例都可以附加属性以维护其状态。类实例也可以有方法(由它们的类定义)来修改它们的状态。
为了理解创建类的必要性,让我们考虑一个示例,假设您想要跟踪可能具有不同属性(如品种、年龄)的狗的数量。如果使用列表,第一个元素可以是狗的品种,而第二个元素可以代表它的年龄。假设有 100 只不同的狗,那么你怎么知道哪个元素应该是哪个?如果您想为这些狗添加其他属性怎么办?这缺乏组织,这是对课程的确切需求。
类创建一个用户定义的数据结构,其中包含自己的数据成员和成员函数,可以通过创建该类的实例来访问和使用。一个类就像一个对象的蓝图。
Python 类的一些要点:
- 类由关键字 class 创建。
- 属性是属于一个类的变量。
- 属性始终是公共的,可以使用点 (.) 运算符进行访问。例如:Myclass.Myattribute
类定义语法:
class ClassName:
# 语句-1
.
.
.
# 语句-N
定义一个类
# 演示定义类的 Python3 程序
class Dog:
pass
在上面的示例中,class 关键字表示您正在创建一个类,后跟该类的名称(在本例中为 Dog)。
类对象
对象是类的实例。一个类就像一个蓝图,而一个实例是具有实际值的类的副本。这不再是一个想法,它是一只真正的狗,就像一只七岁的哈巴狗。您可以拥有许多狗来创建许多不同的实例,但是如果没有类作为指导,您将迷失方向,不知道需要哪些信息。
一个对象包括:
- 状态:由对象的属性表示。它还反映了对象的属性。
- 行为:它由对象的方法表示。它还反映了一个对象对其他对象的响应。
- 身份:它为一个对象赋予一个唯一的名称,并使一个对象能够与其他对象交互。
声明对象(也称为实例化类)
当一个类的对象被创建时,该类被称为实例化。所有实例共享类的属性和行为。但是这些属性的值,即状态对于每个对象都是唯一的。一个类可以有任意数量的实例。
例子:
声明一个对象
# 演示实例化类的 Python3 程序
class Dog:
# 一个简单的类
# attribute 属性
attr1 = "哺乳动物"
attr2 = "狗"
# 示例方法
def fun(self):
print("我是", self.attr1)
print("我是", self.attr2)
# 驱动程序代码
# 对象实例化
qiuqiu = Dog()
# 通过对象访问类属性和方法
print(qiuqiu.attr1)
qiuqiu.fun()
输出:
哺乳动物
我是哺乳动物
我是狗
在上面的示例中创建了一个对象,它是一只名叫 qiuqiu 的狗。这个类只有两个类属性告诉我们 qiuqiu 是狗和哺乳动物。
Python 中的继承
继承是一个类从另一个类派生或继承属性的能力。继承的好处是:
1.它很好地代表了现实世界的关系。
2.提供了代码的可重用性。我们不必一次又一次地编写相同的代码。此外,它允许我们在不修改类的情况下向类添加更多功能。
3.本质上是可传递的,这意味着如果类 B 继承自另一个类 A,那么 B 的所有子类将自动继承自类 A。
下面是一个简单的 Python 继承示例
# 一个演示继承的 Python 程序
# 基类或超类。 注意括号中的 object。(通常,object 是所有类的祖先)
# 在 Python 3.x 中,“class Person”等价于“class Person(object)”
class Person(object):
# 构造函数
def __init__(self, name):
self.name = name
# 获得 name
def getName(self):
return self.name
# 检查此人是否为员工
def isEmployee(self):
return False
# 继承或子类(注意括号中的 Person)
class Employee(Person):
# 这里我们返回 true
def isEmployee(self):
return True
# 驱动程序代码
emp = Person("Haiyong1") # Person 对象
print(emp.getName(), emp.isEmployee())
emp = Employee("Haiyong2") # Employee 对象
print(emp.getName(), emp.isEmployee())
输出:
Haiyong1 False
Haiyong2 True
Python 中的封装
封装是面向对象编程(OOP)中的基本概念之一。它描述了包装数据的想法以及在一个单元内处理数据的方法。这限制了直接访问变量和方法,并且可以防止意外修改数据。为防止意外更改,对象的变量只能通过对象的方法进行更改。这些类型的变量称为私有变量。
类是封装的一个例子,因为它封装了成员函数、变量等所有数据。
考虑一个真实的封装示例,在公司中,有不同的部门,如客服部、财务部、销售部等。财务部处理所有财务交易并记录与财务相关的所有数据。同样,销售部分处理所有与销售相关的活动并保存所有销售记录。现在可能会出现一种情况,财务部的员工出于某种原因需要某月的所有销售数据。在这种情况下,不允许他直接访问销售部的数据。他首先必须联系销售部的经理,然后申请查阅具体数据。这就是封装。在这里,销售部的数据和可以操作它们的员工被包装在一个单一的名称“销售部”下。使用封装也会隐藏数据,在此示例中,销售、财务或客服等部门的数据对任何其他部门都是隐藏的。
Protected 成员
Protected 成员(在 C++ 和 JAVA 中)是不能在类外部访问但可以从类及其子类内部访问的那些成员。要在 Python 中完成此操作,只需按照约定在成员名称前加上一个下划线“_”即可。
尽管 Protected 变量可以在类外以及派生类中访问(在派生类中也可以修改),但习惯上(约定不是规则)不访问受保护的类主体。
注意: __init__
方法是一个构造函数,并在类的对象被实例化后立即运行。
# 演示 Protected 成员的 Python 程序
class Base:
def __init__(self):
# Protected 成员
self._a = 2
# 创建派生类
class Derived(Base):
def __init__(self):
# 调用基类的构造函数
Base.__init__(self)
print("调用基类的 Protected 成员: ",
self._a)
# Modify the protected variable:
self._a = 3
print("调用类外修改的 Protected 成员: ",
self._a)
obj1 = Derived()
obj2 = Base()
# 调用 Protected 成员可以访问,但由于约定不应该这样做
print("访问 obj1 的 Protected 成员: ", obj1._a)
# 在外部访问受保护的变量
print("访问 obj2 的 Protected 成员: ", obj2._a)
输出:
调用基类的 Protected 成员:2
调用类外修改的 Protected 成员:3
访问 obj1 的 Protected 成员:3
访问 obj2 的 Protected 成员:2
Private 成员
Private 成员类似于 Protected 成员,不同之处在于声明为私有的类成员既不能在类外访问,也不能被任何基类访问。在 Python 中,不存在只能在类内部访问的私有实例变量。
但是,要定义 Private 成员,请在成员名称前加上双下划线“__”。
注意:可以通过 python name mangling 在类外部访问 Python 的 Private 成员和 Protected 成员。
Python 中的魔术方法
魔术方法确保了一致的数据模型,该模型保留了内置类的继承特性,同时提供了自定义的类行为。这些方法可以丰富类设计,增强语言的可读性。
魔术方法语法
两边用两个下划线包裹的方法称为魔术方法。魔术方法的背后是重载 Python 的内置方法及其运算符。在这里,_syntax 防止程序员为自定义方法定义相同的名称。每种魔术方法都有其用途。让我们考虑一个检查等价的例子。
例子:
class EquivalenceClass(object):
def __eq__(self, other):
return type(self) == type(other)
print(EquivalenceClass() == EquivalenceClass())
print(EquivalenceClass() == 'MyClass')
输出
True
False
此__eq__
方法采用两个参数——self 和 object——来检查相等性。重要的是要理解,当使用 == 运算符比较两个对象时会调用 __eq__
方法。让我们来看看 python 中一些常见的魔术方法。
常用魔法方法
在 Python 中,我们有各种各样的魔法方法——每一种都有它的用途。下面我们就梳理一下,几种常见的魔法方法:
- 创建:
__init__
和__new__
方法 - 破坏:
__del__
方法 - 类型转换:
__str__
、__int__
、__float__
、__complex__
和__bool__
方法 - 比较:
__eq__
、__ne__
方法
二元运算符的魔术方法:
- vanilla 方法
- reversei 方法
- in-place 方法
一元运算符的魔术方法:
__pos__
方法__neg__
方法__invert__
方法
魔术方法其实就是一种一致的数据模型,可以自定义类行为并增强可读性,而不会丢失其继承的特性。但是在提供自定义功能之前,需要确保是否需要自定义。
Python 中的设计模式
设计模式是软件工程中最重要的部分,因为它们为软件设计中常见的问题提供了通用的可重复解决方案。我们不能将设计模式视为可以直接转换为代码的完成设计。它们只是描述如何高效解决特定问题的模板。
设计模式分类
创造性设计模式:
创建模式提供有关类实例化或对象实例化的基本信息。类创建模式和对象创建模式是创建设计模式的主要分类。虽然类创建模式在实例化过程中有效地使用了继承,但对象创建模式有效地使用委托来完成工作。
创造性设计模式的分类 ——
- 工厂模式
- 抽象工厂模式
- 建造者模式
- 原型模式
- 单例模式
结构设计模式:
结构设计模式是关于组织不同的类和对象以形成更大的结构并提供新功能,同时保持这些结构的灵活性和效率。大多数情况下,他们使用继承来组合所有接口。它还确定了导致结构简化的关系。
结构设计模式的分类——
- 适配器模式
- 桥接模式
- 复合模式
- 装饰器模式
- 外观模式
- 代理模式
- 蝇量模式
行为设计模式:
行为模式都是关于识别对象之间常见的通信模式并实现这些模式。这些模式与算法和对象之间的职责分配有关。
行为设计模式分类——
- 责任链模式
- 命令模式
- 迭代器模式
- 中介模式
- 记忆模式
- 观察者模式
- 状态方模式
- 策略模式
- 模板模式
- 访客模式
举例说明几种常用设计模式
1.工厂设计模式
工厂方法是一种创建型设计模式,它允许接口或类创建对象,但让子类决定要实例化哪个类或对象。使用工厂方法,我们有最好的方法来创建一个对象。这里,对象的创建不向客户端公开逻辑,并且为了创建新类型的对象,客户端使用相同的公共接口。
现在让我们通过一个例子来理解工厂方法:
# 工厂方法的 Python 代码
# 它属于创建型设计模式
class FrenchLocalizer:
""" 只返回法语版本 """
def __init__(self):
self.translations = {"car": "voiture", "bike": "bicyclette","cycle":"cyclette"}
def localize(self, msg):
"""使用翻译更改信息"""
return self.translations.get(msg, msg)
class SpanishLocalizer:
"""只返回西班牙语版本"""
def __init__(self):
self.translations = {"car": "coche", "bike": "bicicleta","cycle":"ciclo"}
def localize(self, msg):
"""使用翻译更改信息"""
return self.translations.get(msg, msg)
class EnglishLocalizer:
"""只需返回相同的消息"""
def localize(self, msg):
return msg
def Factory(language ="English"):
"""工厂方法"""
localizers = {
"French": FrenchLocalizer,
"English": EnglishLocalizer,
"Spanish": SpanishLocalizer,
}
return localizers[language]()
if __name__ == "__main__":
f = Factory("French")
e = Factory("English")
s = Factory("Spanish")
message = ["car", "bike", "cycle"]
for msg in message:
print(f.localize(msg))
print(e.localize(msg))
print(s.localize(msg))
2.单例设计模式
单例方法是一种创建设计模式,是我们可用的最简单的设计模式之一。这是一种提供一个且仅一个特定类型的对象的方法。它只涉及一个类来创建方法和指定对象。在单例设计模式的经典实现中,我们简单地使用静态方法来创建能够返回共享资源的 getInstance 方法。我们还使用所谓的虚拟私有构造函数来引发异常,但这并不是必需的。
# 单例设计模式的经典实现
class Singleton:
__shared_instance = 'GeeksforGeeks'
@staticmethod
def getInstance():
"""Static Access Method"""
if Singleton.__shared_instance == 'GeeksforGeeks':
Singleton()
return Singleton.__shared_instance
def __init__(self):
"""virtual private constructor"""
if Singleton.__shared_instance != 'GeeksforGeeks':
raise Exception ("This class is a singleton class !")
else:
Singleton.__shared_instance = self
# main 方法
if __name__ == "__main__":
# 创建单例类的对象
obj = Singleton()
print(obj)
# 选择类的实例
obj = Singleton.getInstance()
print(obj)
3.外观设计模式
外观设计模式是一种结构设计模式,它为更复杂的系统提供更简单的统一接口。Facade 这个词意味着系统的表面,或者特别是复杂系统的外部界面,由几个子系统组成。
想象一下,我们有一台洗衣机,它可以洗衣服、漂洗衣服和旋转衣服,但所有任务都是分开的。由于整个系统相当复杂,我们需要将子系统的复杂性抽象出来。我们需要一个可以自动完成整个任务而不受我们干扰或干扰的系统。
"""以洗衣机为例的外观设计模式"""
class Washing:
'''子系统 # 1'''
def wash(self):
print("Washing...")
class Rinsing:
'''子系统 # 2'''
def rinse(self):
print("Rinsing...")
class Spinning:
'''子系统 # 3'''
def spin(self):
print("Spinning...")
class WashingMachine:
'''Facade'''
def __init__(self):
self.washing = Washing()
self.rinsing = Rinsing()
self.spinning = Spinning()
def startWashing(self):
self.washing.wash()
self.rinsing.rinse()
self.spinning.spin()
""" main 方法 """
if __name__ == "__main__":
washingMachine = WashingMachine()
washingMachine.startWashing()
使用设计模式的优势
- 可重用性:通过使用继承,它们有助于使代码可重用,因此我们可以在多个项目中使用它们。
- 透明:它提高了所有将来要使用它的开发人员的代码透明度。
- 已建立的解决方案:我们可以盲目相信设计模式提供的解决方案,因为它们在关键阶段得到了充分证明和证明。
- 已建立的沟通:设计模式使设计师之间的沟通更加有效。当软件专业人员在讨论系统设计时提到用于解决特定问题的模式名称时,他们可以立即在脑海中描绘出高级设计。
- 高效开发:设计模式有助于以最小的耦合开发高度内聚的模块。
- 点赞
- 收藏
- 关注作者
评论(0)