面向对象编程(OOP):理解类、封装性的关键概念

简介: 面向对象编程(OOP):理解类、封装性的关键概念

对象(Object)

什么是对象?

对象是内存中专门用来存储数据的一块区域。对象中可以存放各种数据,比如数字、布尔值、代码。对象由三部分组成:

  1. 对象的标识(id)
  2. 对象的类型(type)
  3. 对象的值(value)

面向对象(OOP)

Python是一门面向对象的编程语言。所谓的面向对象的语言,简单理解就是语言中的所有操作都是通过对象来进行的。

面向过程的编程语言

面向过程指将我们的程序的逻辑分解为一个一个的步骤,通过对每个步骤的抽象,来完成程序。例如,孩子上学的过程可以拆分为多个步骤:

  1. 妈妈起床
  2. 妈妈上厕所
  3. 妈妈洗漱
  4. 妈妈做早饭
  5. 妈妈叫孩子起床
  6. 孩子上厕所
  7. 孩子要洗漱
  8. 孩子吃饭
  9. 孩子背着书包上学校

面向过程的编程思想将一个功能分解为一个一个小的步骤,通过完成一个一个小的步骤来完成一个程序。这种编程方式比较简单,符合人类的思维。但是它的可复用性低,并且难于维护。

面向对象的编程语言

面向对象的编程语言关注的是对象,而不关注过程。对于面向对象的语言来说,一切都是对象。例如,孩他妈起床叫孩子上学。

面向对象的编程思想将所有的功能统一保存到对应的对象中,要使用某个功能,直接找到对应的对象即可。这种方式编写的代码容易阅读、易于维护,也容易复用。但是这种方式编写起来稍微麻烦一点,不太符合常规的思维。

综上所述,面向对象的编程思想主要包括两步:

  1. 找对象
  2. 搞对象

类(class)

在Python中,我们可以使用内置对象 (如int, float, str等) 来创建对象。但是,不能满足所有的需求,因此我们经常需要自定义一些对象。简单地说,类就相当于一个图纸。我们在程序中需要根据类来创建对象。也有人称对象是类的实例(instance)。如果多个对象是通过一个类创建的,我们称这些对象是一类对象,就像 int()、float()、bool()、str()、list()、dict() 之类的对象一样。在定义自己的类时,需要使用大写字母开头,使用大驼峰命名法(帕斯卡命名法)来对类命名。

#定义一个简单的类
class MyClass():
    pass
mc = MyClass()

使用类创建对象的流程

使用类来创建对象,就像调用一个函数一样。它的流程如下:

1.创建一个变量

2.在内存中创建一个新对象

3.将对象的id赋值给变量

类的定义

实际上,类和对象都是对现实生活中的事物或程序中的内容的抽象。在类的代码块中,我们可以定义变量和函数。变量会成为该类实例的公共属性,所有该类实例都可以通过 对象.属性名 的形式访问。函数会成为该类实例的公共方法,所有该类实例都可以通过 对象.方法名() 的形式调用方法。在定义方法时,至少要定义一个形参。方法调用时,解析器会先在当前对象中寻找是否含有该属性或方法,如果没有,则去当前对象的类对象中去寻找。如果类对象中依然没有,则报错。

#定义一个简单的人类
class Person :
    name = 'swk' # 公共属性,所有实例都可以访问
    def say_hello(self) :
        print('你好!我是 %s' %self.name)
p1 = Person()
p2 = Person()
p1.name = '猪八戒'
p1.say_hello() # '你好!我是 猪八戒'
p2.say_hello() # '你好!我是 swk'

代码演示

#定义一个简单的类
class MyClass():
    pass
#使用MyClass创建一个对象
mc = MyClass() # mc就是通过MyClass创建的对象,mc是MyClass的实例
mc_2 = MyClass()
mc_3 = MyClass()
mc_4 = MyClass()
# isinstance()用来检查一个对象是否是一个类的实例
result = isinstance(mc_2,MyClass)
#现在我们通过MyClass这个类创建的对象都是一个空对象
#也就是对象中实际上什么都没有,就相当于是一个空的盒子
#可以向对象中添加变量,对象中的变量称为属性
#语法:对象.属性名 = 属性值
mc.name = '孙悟空'
mc_2.name = '猪八戒'
print(mc_2.name)
#定义一个简单的人类
class Person :
    name = 'swk' # 公共属性,所有实例都可以访问
    def say_hello(self) :
        print('你好!我是 %s' %self.name)
p1 = Person()
p2 = Person()
p1.name = '猪八戒'
p1.say_hello() # '你好!我是 猪八戒'
p2.say_hello() # '你好!我是 swk'

初始化方法和实例属性

在类中,我们可以定义一个特殊的方法,称为初始化方法(init),它会在创建一个对象时自动调用。初始化方法可以接受参数,并将这些参数赋值给对象的属性。通过这种方式,我们可以为每个对象设置不同的初始值。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def say_hello(self):
        print(f"你好!我是{self.name},今年{self.age}岁。")

在上面的代码中,我们定义了一个Person类,它有两个实例属性:nameage。初始化方法接受两个参数,并将它们分别赋值给对象的属性。通过创建对象并调用say_hello方法,我们可以访问和修改这些属性。

类属性和类方法

除了实例属性和实例方法,类还可以有类属性和类方法。

类属性是属于类本身的属性,而不是属于实例的属性。所有该类的实例都可以访问和修改类属性。

class Person:
    count = 0  # 类属性
    def __init__(self, name):
        self.name = name
        Person.count += 1  # 每创建一个实例,count加1
    @classmethod
    def get_count(cls):
        return cls.count  # 使用cls访问类属性

在上面的代码中,我们定义了一个count类属性,它记录了创建的实例个数。每当创建一个实例时,通过初始化方法将类属性count加1。通过类方法get_count(),我们可以获取到目前创建的实例个数。

继承和多态

Python中的类还支持继承,一个类可以从另一个类继承属性和方法。子类可以重写父类的方法,实现多态的效果。

class Animal:
    def __init__(self, name):
        self.name = name
    def speak(self):
        pass
class Dog(Animal):
    def speak(self):
        print(f"{self.name}汪汪叫")
class Cat(Animal):
    def speak(self):
        print(f"{self.name}喵喵叫")

在上面的代码中,我们定义了一个Animal类,它有一个speak方法。然后,我们定义了DogCat两个子类分别继承Animal类。子类可以重写父类的方法,这就是多态的一种体现。通过创建DogCat对象,我们可以调用它们各自的speak方法。

魔术方法

除了初始化方法(init)之外,Python中还有许多特殊方法,也被称为魔术方法(magic methods)。这些特殊方法以双下划线开头和结尾,它们在特定的时刻自动调用。

class Person:
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return f"Person对象:{self.name}"
    def __eq__(self, other):
        return self.name == other.name

在上面的代码中,我们定义了两个魔术方法:__str____eq__

  • __str__方法用于定义对象的字符串表示。当调用print函数或使用str()函数时,会自动调用该方法并返回一个字符串表示。
  • __eq__方法用于定义对象的相等性。它接受另一个对象作为参数,并根据自定义的逻辑判断两个对象是否相等。

通过实现这些魔术方法,我们可以更好地控制对象的行为,并使其更符合我们的预期。

小结

在本章中,我们介绍了Python类的基本概念和用法。从初始化方法到实例属性、类属性、类方法、继承和多态,我们一步步深入了解了类的各种特性和用法。同时,我们还了解了魔术方法的作用和用法,可以通过实现这些方法来定制类的行为。

类的封装性

在面向对象的编程中,封装是一种重要的概念。它指的是将数据和方法组合成一个单一的实体,并对外部隐藏具体的实现细节。

Python中的类提供了封装的机制。我们可以使用访问修饰符来控制属性和方法的可访问性。

  • 公有访问修饰符:没有使用任何修饰符,所有属性和方法默认为公有。公有属性和方法可以在类内部和外部访问。
  • 私有访问修饰符:使用双下划线(__)作为前缀来定义私有属性和方法。私有属性和方法只能在类内部访问,无法在类外部直接访问。
class Person:
    def __init__(self, name):
        self.__name = name  # 私有属性
    def __say_hello(self):  # 私有方法
        print(f"你好!我是{self.__name}。")
    def greet(self):
        self.__say_hello()

在上面的代码中,namesay_hello都是私有成员。使用双下划线作为前缀可以定义私有属性和方法。在类的内部,我们可以直接访问这些私有成员。而在类的外部,无法直接访问私有成员,但可以通过公有方法间接访问。

属性的访问器和设置器

除了直接访问属性,我们还可以使用属性访问器(getter)和属性设置器(setter)来控制对属性的访问和修改。

class Person:
    def __init__(self, name):
        self.__name = name
    @property
    def name(self):  # 属性访问器
        return self.__name
    @name.setter
    def name(self, value):  # 属性设置器
        if isinstance(value, str):
            self.__name = value
        else:
            raise ValueError("姓名必须是字符串类型")

在上面的代码中,我们使用@property装饰器定义了一个属性访问器,名为name()。通过访问obj.name,我们可以获取私有属性__name的值。然后,我们使用@name.setter装饰器定义了一个属性设置器,名也为name()。通过赋值obj.name = value,我们可以修改私有属性__name的值。

这样做的好处是,在外部使用对象属性时,我们可以像访问普通属性一样,而无需直接访问私有属性。

小结

在本文中,我们介绍了Python类的封装性和属性访问控制。通过使用访问修饰符、私有属性和方法,我们可以隐藏类的具体实现细节,并提供公有接口供外部使用。我们还学习了如何使用属性访问器和设置器来控制对属性的访问和修改。

总结

本文介绍了面向对象编程中的一些重要概念和技术,包括对象、类、继承、多态、魔术方法等。通过使用类和对象,我们可以将数据和方法组合成一个单一的实体,实现代码的封装和复用。

在面向过程的编程语言中,主要关注程序的过程和函数。而在面向对象的编程语言中,我们将程序分解成一个个的对象,每个对象都有自己的数据和方法。这种方式更加灵活和易于理解。

类是对象的模板,通过定义类可以创建出多个实例对象。类由属性和方法组成,属性存储对象的数据,方法定义对象的行为。

初始化方法和实例属性用于在创建对象时初始化对象的状态。类属性是所有实例共享的属性,类方法是作用于整个类而非单个实例的方法。

继承和多态是面向对象编程中的两个重要概念。通过继承,我们可以创建新的类并从现有的类继承属性和方法。多态允许不同的对象对相同的方法进行不同的实现,提高了代码的灵活性和可扩展性。

魔术方法是Python中特殊命名的方法,用于实现特定的功能或行为,如初始化、比较、运算符重载等。

此外,本文还介绍了类的封装性和属性的访问控制。通过使用访问修饰符、私有属性和方法,可以隐藏类的具体实现细节,并提供公有接口供外部使用。属性访问器和设置器可以控制对属性的访问和修改,增加了代码的安全性和可维护性。

总而言之,面向对象编程是一种强大的编程范式,通过将程序分解成对象的方式,可以实现代码的模块化、复用和灵活性。掌握类的定义、继承、多态、魔术方法等概念和技术,能够编写出更加结构化和可扩展的代码。

相关文章
|
网络虚拟化
VLAN(虚拟局域网)简介与配置指南
VLAN(虚拟局域网)简介与配置指南
816 1
|
机器学习/深度学习 人工智能 API
『GitHub项目圈选06』推荐5款本周 超火 的开源AI项目
『GitHub项目圈选06』推荐5款本周 超火 的开源AI项目
1202 0
|
存储 C语言
【C语言基础考研向】10 字符数组初始化及传递和scanf 读取字符串
本文介绍了C语言中字符数组的初始化方法及其在函数间传递的注意事项。字符数组初始化有两种方式:逐个字符赋值或整体初始化字符串。实际工作中常用后者,如`char c[10]="hello"`。示例代码展示了如何初始化及传递字符数组,并解释了为何未正确添加结束符`\0`会导致乱码。此外,还讨论了`scanf`函数读取字符串时忽略空格和回车的特点。
344 8
|
10月前
|
Linux
如何查看当前的NFS挂载信息?
如何查看当前的NFS挂载信息?
1580 2
|
JavaScript
Vue3相关组件项目依赖依赖版本信息
这篇文章展示了一个Vue 3项目中使用的组件和库的依赖版本信息,包括`ant-design-vue`、`swiper`、`vue`、`vue-router`等,以及开发依赖如`vite`、`vue-tsc`、`eslint`等。
186 0
Vue3相关组件项目依赖依赖版本信息
Ueditor——请求后台配置项http错误,上传功能将不能正常使用
Ueditor——请求后台配置项http错误,上传功能将不能正常使用
184 0
Ueditor——请求后台配置项http错误,上传功能将不能正常使用
|
弹性计算 大数据 测试技术
阿里云服务器哪个好用便宜?2024年阿里云便宜购买配置价格整理总结
随着云计算技术的日益成熟,云服务器已成为企业和个人用户的首选。在众多的云服务提供商中,阿里云和腾讯云以其稳定的服务、强大的性能和优惠的价格赢得了广大用户的青睐。阿里云推出的多款云服务器实例中,2核2G3M轻量应用服务器一年仅需62元,而经济型e实例云服务器ECS和通用算力型u1实例云服务器ECS则提供了更广泛的选择。其中,2核2G3M经济型e实例一年99元,2核4G通用算力型u1实例一年706.25元,更有4核8G、4核16G等高性能配置供用户选择。这些实例在性价比上表现突出,尤其是通用算力型u1实例,性能与价格俱佳。对于性能要求不高的用户来说,它是非常合适的选择;而对性能有更高要求的用户。
|
存储 关系型数据库 MySQL
MySQL ⽀持哪些存储引擎?默认使⽤哪个?MyISAM 和 InnoDB 引擎有什么区别,如何选择?
MySQL ⽀持哪些存储引擎?默认使⽤哪个?MyISAM 和 InnoDB 引擎有什么区别,如何选择?
2081 0
|
Linux
Linux mkdir命令:创建目录(文件夹)
mkdir 命令,是 make directories 的缩写,用于创建新目录,此命令所有用户都可以使用。mkdir 命令的基本格式为: [root@localhost ~]# mkdir [-mp] 目录名 -m 选项用于手动配置所创建目录的权限,而不再使用默认权限。 -p 选项递归创建所有目录,以创建 /home/test/demo 为例,在默认情况下,你需要一层一层的创建各个目录,而使用 -p 选项,则系统会自动帮你创建 /home、/home/test 以及 /home/test/demo。 【例 1】建立目录。 [root@localhost ~]#mkdir cangls
867 0