目录
前言
预习网安也有一段时间了,但是编程不能荒废,今天开始把从类开始自己理解和笔记,一点一点总结的写出出来。
思维导图
1, 面向对象编程概述
面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它将程序中的数据和操作数据的方法组织成对象。对象是一个具有特定属性和行为的实体,它可以通过调用方法来执行特定的操作。
根据代码组织方式的不同,编程语言可以分为以下两种:
面向过程语言
:面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再依次调用,类似流水线的工作原理。
面向对象语言
:面向对象是把构成问题事务分解成各个对象,依靠各个对象之间的交互推动程序执行,进而实现问题的解决。建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在完整解决问题步骤中的行为。
1.1,OOP的产生
面向对象编程(OOP)产生于20世纪60年代和70年代,主要由一些研究人员和编程语言设计者倡导和发展。
1.2,OOP的核心思想
它的核心思想是将现实世界中的事物抽象成对象,并通过对象之间的交互来实现程序的设计和开发。
对象
作为程序的基本单位
,将程序和数据封装于其中,以提高程序的重用性、灵活性和可扩展性。
类
是创建对象
的模板
,而对象
是类的实例化
。一个类可以创建多个对象。例如花就是一个类,而玫瑰花,荷花,白玫瑰,栀子花,蔷薇,三叶草。指的就是一个类可以创建多个对象。
通俗来说类就是一个大范围的抽象事物,例如动物,植物等,而对象指的是具体的事物,例如猫,花,
指的是具体的事物。
当然花也可作为类,然后玫瑰花就是花的实例化对象,类指的是一个大类是一个抽象的事物,而对象是真实的某个事物。
操作方法:
在采用面向对象思想编程时,可依次采用以下步骤:
(1)分析哪些动作是由哪些实体发出的;
(2)定义这些实体,为其增加相应的属性和功能;
(3)让实体去执行相应的功能或动作。
1.3,OOP特征
面向对象的编程机制有以下四大特征:
1.继承(Inheritance):OOP支持通过继承机制创建新的类(子类)从已有的类(父类)继承属性和方法。子类可以重用父类的代码,并可以添加自己的额外功能。
作用:继承提供了代码的重用性和可扩展性。
2.封装(Encapsulation):OOP通过封装将相关的数据和方法封装在一个单元(对象)中。对象对外部世界隐藏了内部实现细节,只暴露必要的接口供外部访问。
作用:封装提高了代码的安全性和可维护性。
3.多态(Polymorphism):多态意味着一个对象可以以不同的方式呈现,即同一操作作用于不同的对象,可以产生不同的行为。
作用:多态通过接口的使用来实现,提高了代码的灵活性和可扩展性。
4.抽象(Abstraction):OOP通过抽象机制隐藏了对象的复杂性,只关注关键的属性和方法。抽象类和接口可以定义抽象的属性和方法,而具体的子类实现这些抽象定义。
作用:抽象提供了一种概括和简化问题的方式。
2,类和对象
2.1,类的创建
Python语言中,使用class关键字来创建类,其创建方式如下:
class Cat(self):
# 一次模拟小猫的实验
self表示要继承的父类,一般情况下self表示类本身,默认继承object类
类、属性和方法的命名约定惯例如下:
类名
表示实例的抽象,命名时首字母大写
;属性
使用名词作为名字,比如name、age、weight等;方法
名一般指对属性的操作,其命名规则一般采用动词加属性名称形式。
新式类
:Python3.x中类定义的默认方式,必须继承object方法,其典型定义方式如下图:
# 新式类是指继承object的类
class Cat(object):
pass
新式类
修复了经典类的一些bug(如多重继承时的歧义等),并且提供了对类方法
和静态方法
的支持。
在Python3.x中,如果没有显示指明要继承的父类,则默认继承object
类。
class Cat:
pass
class Cat():
pass
class Cat(object):
pass
Python3.x中,无需继承时,例子中三种类的创建效果一样。自动继承object类。
新式类添加了一些内置属性和方法,如下所示:
__name__ :属性的名字
__doc__ :属性的文档字符串
__get__(object) :获取对象属性值的方法
__set__(object, value) :设置对象属性值的方法
__delete__(object, value) :删除对象属性的方法
2.2,类的属性
class A():
age = 10
obj2 = A()
obj3 = A()
这里用通俗的话来讲的话就是,A为类示例,按照我的理解的话,就是A是由直接创建的类,而abj2与obj3,都是用类A来创建的对象,而 等号后的A()代表为他们示例化,也就是将类A所拥有的属性赋予给对象。
如例子所示,存在三个实例,分别是类实例
A和对象实例
obj2、obj3。
在情形1中,obj2和obj3这两个对象实例共享类实例A的属性age;
# 情形1
print(obj2.age, obj3.age, A.age)
在情形2中,显示修改了对象实例obj2的属性,然后obj2的属性值就独立了。
# 情形2
obj2.age+=2
print(obj2.age, obj3.age, A.age)
在情形3中,修改了类实例A的属性,没有修改过属性的obj3的属性还是会共享类示例A的值。
# 情形3
A.age+=3
print(obj2.age, obj3.age, A.age)
结果如图所示:
情景1:
10 10 10
情景2:
12 10 10
情景3:
12 13 13
在情形2中已经修改了对象实例obj2的属性值age,其属性值和类实例A的属性值已经独立。
而对象实例obj3的属性从来没有修改过,所以它还是和类实例A的属性值保持一致。
Python语言对于属性的设置采用“
类.属性 = 值
”或“实例.属性 = 值
”的形式。如上例中obj2.age += 2等价于
obj2.age = obj2.age + 2,该语句包含了属性获取及属性设置两个操作。Python语言中的属性操作遵循三个规则:
(1)属性的获取是按照从下到上的顺序来查找属性;
(2)类和实例是两个完全独立的对象;
(3)属性设置是针对实例本身进行的。
2.3,类的方法
类的方法是定义在类中的函数。它们用于描述类的行为和操作,可以访问类的属性和其他方法。类的方法可以执行各种任务,例如修改属性的值、返回计算结果、与其他对象进行交互等。
在大多数编程语言中,类的方法可以被调用来执行特定的操作。通常,方法由类的实例调用,以便在特定的对象上执行相应的操作。方法可以使用关键字
self
引用当前对象的实例,并通过该实例访问类的属性和其他方法。
下面是一个简单的Python类,其中包含一个方法:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
print(f"Hello, my name is {self.name} and I'm {self.age} years old.")
person = Person("Alice", 25)
person.greet()
在上面的例子中,
Person
类有一个greet
方法,用于向用户打招呼。该方法访问实例的name
和age
属性,并将其打印到控制台上。
类方法还可以根据访问权限和调用方式进一步细分为公有方法、私有方法、类方法和静态方法。下面是对它们的简要介绍:
类型 | 描述 |
---|---|
公有方法 | 公有方法是可以从类的内部和外部访问的方法。它们可以通过类的实例或类本身进行调用。公有方法在类的封装性方面起到了很好的平衡作用,并且常用于提供对类属性的封装访问接口。 |
私有方法 | 私有方法是只能在类的内部访问的方法。它们以一个下划线作为前缀,例如_private_method 。私有方法用于封装类的实现细节,并且不能从类的外部直接访问或调用。 |
类方法 | 类方法是绑定到类而不是实例的方法。它们使用@classmethod 装饰器进行修饰,并将类作为第一个参数,通常被约定为cls 。类方法可以通过类本身进行调用,并且可以在方法内部访问类的属性,但不能直接访问实例的属性。 |
静态方法 | 静态方法是不与类或实例绑定的普通函数。它们使用@staticmethod 装饰器进行修饰,并没有特殊的参数约定。静态方法可以通过类或实例进行调用,但不能访问类或实例的属性。它们通常用于实现与类相关但不依赖于实例的功能。 |
2.4, 内部类
在Python中,内部类也是一种定义在其他类内部的类。Python支持两种类型的内部类:
成员内部类(Member Inner Class):成员内部类是定义在外部类的成员位置,并与外部类的实例相关联的类。它可以访问外部类的属性和方法,并且必须通过外部类的实例进行实例化。成员内部类使用外部类的实例作为创建者,因此无法在没有外部类实例存在的情况下创建对象。
下面是一个Python的成员内部类示例:
class Outer:
def __init__(self):
self.outer_variable = 10
def outer_method(self):
inner = self.Inner()
inner.inner_method()
class Inner:
def inner_method(self):
print("Inner method - outer_variable:", self.outer_variable)
# 在外部类的实例上使用内部类
outer = Outer()
outer.outer_method()
嵌套类(Nested Class): 嵌套类是定义在外部类的内部,与外部类的实例无关的类。它可以在外部类的作用域内直接实例化,不需要外部类的实例。与成员内部类不同,嵌套类访问不到外部类的实例变量,只能访问外部类的静态成员或全局变量。
下面是一个Python的嵌套类示例:
class Outer:
outer_static_variable = 20
@staticmethod
def outer_static_method():
inner = Outer.Inner()
inner.inner_method()
class Inner:
def inner_method(self):
print("Inner method - outer_static_variable:", Outer.outer_static_variable)
# 直接使用内部类
inner = Outer.Inner()
inner.inner_method()
# 通过外部类调用静态内部类
Outer.outer_static_method()
注意:
无论是成员内部类还是嵌套类,它们提供了一种在外部类内部组织和封装代码的方式,并可以访问外部类的成员。需要注意的是,Python的内部类没有像Java那样的严格区分静态和非静态内部类的概念。相反,Python的内部类可以访问外部类的实例变量,并且内部类的方法可以通过外部类的实例进行调用。
2.5, 魔术方法
在Python中,魔术方法(Magic Methods),也称为特殊方法(Special Methods),是一种以双下划线(__)开头和结尾的特殊命名方法。它们用于在类中定义一些特定的行为,以实现某些功能或模拟特定操作。
以下是一些常用的类中的魔术方法:
__init__(self, ...)
: 构造方法,创建对象时被调用,用于初始化对象的属性。
__str__(self)
: 字符串表示方法,返回对象的字符串表示。
__repr__(self)
: 对象表示方法,返回对象的表达式字符串。
__len__(self)
: 长度方法,返回对象的长度。
__getitem__(self, key)
: 索引访问方法,允许使用索引访问对象的元素。
__setitem__(self, key, value)
: 索引赋值方法,允许使用索引设置对象的元素。
__delitem__(self, key)
: 索引删除方法,允许使用索引删除对象的元素。
__iter__(self)
: 迭代方法,返回一个迭代器对象,允许使用for...in
进行迭代操作。
__next__(self)
: 迭代器方法,返回迭代器中的下一个元素。
__contains__(self, item)
: 成员关系方法,判断对象是否包含指定元素。
__call__(self, ...args, ...kwargs)
: 可调用方法,使对象可以像函数一样被调用。
3.类间关系
3.1, 依赖关系
在面向对象编程中,类之间的依赖关系描述了一个类对象在某些情况下依赖于另一个类对象,即一个类对象需要使用到另一个类对象的功能或数据。
举例来说,假设有两个类:
Car
(车)和Engine
(引擎)。Car
类需要使用Engine
类来提供动力。在这种情况下,Car
类依赖于Engine
类。
class Engine:
def start(self):
print("Engine started")
class Car:
def __init__(self):
self.engine = Engine() # 创建一个Engine对象作为Car的属性
def start_engine(self):
self.engine.start() # 调用Engine对象的方法
# 创建Car对象并启动引擎
my_car = Car()
my_car.start_engine()
我来解读一下这个代码,就从Car类开始,先给类中的engine赋予Engine()这个类作为属性,然后,定义了一个start_engine方法,方法中self.engine调用了Engine类中的start方法。
然后实例化Car类创建了一个my_car对象,然后使用对象调用Car类中的start_engine方法。然后就会按照我上面大解读,一步一步,最后打印出“Engine started”
3.2, 关联关系
关联关系是类之间的一种关系,其中一个类对象和另一个类对象之间存在某种关联,但彼此之间不一定具有强依赖关系。在关联关系中,一个类对象可以通过其他类对象来访问其功能或数据,但它们之间相对独立。
举例来说,假设有两个类:
Teacher
(老师)和Student
(学生)。一个老师可以教多个学生,而一个学生也可以找多个老师辅导。在这种情况下,Teacher
类和Student
类之间存在一个关联关系。
class Teacher:
def __init__(self, name):
self.name = name
def teach(self):
print(f"{self.name} is teaching")
class Student:
def __init__(self, name):
self.name = name
self.teachers = [] # 创建一个列表用于存储老师对象
def add_teacher(self, teacher):
self.teachers.append(teacher) # 添加老师对象到学生的老师列表中
def get_teachers(self):
for teacher in self.teachers:
print(f"{self.name} gets assistance from {teacher.name}")
# 创建Teacher对象
teacher1 = Teacher("John")
teacher2 = Teacher("Sarah")
# 创建Student对象
student1 = Student("Alice")
student2 = Student("Bob")
# 学生和老师之间的关联关系
student1.add_teacher(teacher1)
student1.add_teacher(teacher2)
student2.add_teacher(teacher2)
# 调用对象的方法来展示关联关系
student1.get_teachers()
student2.get_teachers()
这个代码相比于上一个依赖关系,是很容易理解的,只需要按照顺序一点一点解读即可。
3.3, 继承关系
继承是面向对象编程中的一种重要概念,通过继承可以创建新类并从现有类继承属性和方法。在继承关系中,存在一个父类(或称为基类、超类)和一个或多个子类(或称为派生类)。
继承关系的主要优点是代码重用和扩展性。通过继承,子类可以重复使用父类的代码,而不需要重新编写相同的代码。此外,子类还可以在继承的基础上添加新的功能或行为,以满足特定需求。
class Animal:
def __init__(self, name):
self.name = name
def make_sound(self):
pass # 父类的方法,用于通用的方法定义
class Dog(Animal): # Dog类继承自Animal类
def make_sound(self):
return "Woof!" # 重写了父类的make_sound方法
class Cat(Animal): # Cat类继承自Animal类
def make_sound(self):
return "Meow!" # 重写了父类的make_sound方法
# 创建Animal对象
animal = Animal("Generic Animal")
print(animal.name)
# 创建Dog对象
dog = Dog("Buddy")
print(dog.name)
print(dog.make_sound())
# 创建Cat对象
cat = Cat("Whiskers")
print(cat.name)
print(cat.make_sound())
这段代码用这句话就容易理解了,子类继承了父类的属性和方法,并可以在此基础上添加新的属性和方法,或者对父类的方法进行重写。
4.总结
1.通过介绍面向对象的产生由来和核心思想,使初学者认识面向对象编程的基本概念。
2.通过介绍Python语言中类和对象定义和使用的基本概念、流程,使得开发者了解Python语言中面向对象编程的基本流程,并初步掌握面向对象编程的方法。
3.介绍了Python语言面向对象编程时类之间关系的相关知识,包括依赖关系、关联关系、继承关系等。
每日一言
最好不要对距离那样的东西期待太多。
如果我的学习笔记对你有用,不妨点赞收藏一下,感谢你的支持,当然也欢迎大佬给我一下建议或是对笔记中的不足进行补充,对我学习大有帮助,谢谢。