Loading... ## 面向对象——类,封装 ### 什么是对象? - 对象是内存中专门用来存储数据的一块区域。 - 对象中可以存放各种数据(比如:数字、布尔值、代码) - 对象由三部分组成: 1.对象的标识(id) 2.对象的类型(type) 3.对象的值(value) ## 面向对象(oop) - Python是一门面向对象的编程语言 - 所谓的面向对象的语言,简单理解就是语言中的所有操作都是通过对象来进行的 - 面向过程的编程的语言 - 面向过程指将我们的程序的逻辑分解为一个一个的步骤, 通过对每个步骤的抽象,来完成程序 - 例子: - 孩子上学 1.妈妈起床 2.妈妈上厕所 3.妈妈洗漱 4.妈妈做早饭 5.妈妈叫孩子起床 6.孩子上厕所 7.孩子要洗漱 8.孩子吃饭 9.孩子背着书包上学校 - 面向过程的编程思想将一个功能分解为一个一个小的步骤, 我们通过完成一个一个的小的步骤来完成一个程序 - 这种编程方式,符合我们人类的思维,编写起来相对比较简单 - 但是这种方式编写代码的往往只适用于一个功能, 如果要在实现别的功能,即使功能相差极小,也往往要重新编写代码, 所以它可复用性比较低,并且难于维护 - 面向对象的编程语言 - 面向对象的编程语言,关注的是对象,而不关注过程 - 对于面向对象的语言来说,一切都是对象 - 例子: 1.孩他妈起床叫孩子上学 - 面向对象的编程思想,将所有的功能统一保存到对应的对象中 比如,妈妈功能保存到妈妈的对象中,孩子的功能保存到孩子对象中 要使用某个功能,直接找到对应的对象即可 - 这种方式编写的代码,比较容易阅读,并且比较易于维护,容易复用。 - 但是这种方式编写,不太符合常规的思维,编写起来稍微麻烦一点 - 简单归纳一下,面向对象的思想 1.找对象 2.搞对象 ## 类(class) - 相当于一个模板,或者蓝图,用来创建对象 - int,float,bool都是类,但是他们都是自带的类,有时候不能满足需求,所以需要自定义 - 我们创建的类使用大驼峰命名法,即大写字母开头,其后每个单词首字母大写。 - 类也属于对象,类属于'type'类型的对象 ### 类的定义 - 类和对象是对现实生活中事物的抽象 - 所有事物都由两部分构成: 1. 数据(属性) 2. 行为(方法) - 在类中,可以自定义函数和变量,变量会成为实例们的公共属性,所有实例均可以访问,函数也会成为公共函数,可以使用实例名.函数名的方法调用。 - 调用方法时,会将本身传入参数,因此定义任意函数必须写一个参数,通常这个参数规定为'self' - 注意:一般情况下,属性保存到实例对象中,而方法保存到类对象中 ```python class Person(): def function_1(self, a, b, ...): pass def function_2(self, a, b, ...): pass def function_3(self, a, b, ...): pass ... p1 = Person() p1.name = 'wyy' ``` ### 特殊方法(\__init__) - 之前说到,属性一般保存在实例中,所以实际有可能出现下面这种情况: ```python p1 = Person() p1.name = 'wyy' p2 = Person() p2.name = 'zhl' p3 = Person() p3.name = 'dkr' ... ``` - 这样很麻烦,而且有可能忘记初始化一些必须的变量,所以出现了\__init__方法 - 这个方法不需要我们手动调用,它会在实例被创建时自动执行,作用可以传入参数,并且初始化一些函数内变量,下面例子: ```python class Person(): def __init__(self, name, age): self.name = name self.age = age def say_hello(self): print("Hi, I'm %s" %self.name) p1 = Person('wyy', 16) p1.say_hello() ``` - 这样就可以很方便的初始化变量,而且忘记写还会报错。 ### 总结类的基本结构 ```python class 类名([父类]): 公共属性... def __init__(self, a, b, ...): pass def method_1(self, a, b, ...): pass def method_2(self, a, b, ...): pass ... ``` ## 封装 - 封装是面向对象的三大特性之一 - 封装指的是隐藏对象中一些不希望被外部所访问到的属性或方法 - 如何隐藏一个对象中的属性? - 将对象的属性名,修改为一个外部不知道的名字 - 如何获取(修改)对象中的属性? - 需要提供一个getter和setter方法使外部可以访问到属性 - getter 获取对象中的指定属性(get_属性名) - setter 用来设置对象的指定属性(set_属性名) - 使用封装,确实增加了类的定义的复杂程度,但是它也确保了数据的安全性 1. 隐藏了属性名,使调用者无法随意的修改对象中的属性 2. 增加了getter和setter方法,很好的控制的属性是否是只读的 - 如果希望属性是只读的,则可以直接去掉setter方法 - 如果希望属性不能被外部访问,则可以直接去掉getter方法 3. 使用setter方法设置属性,可以增加数据的验证,确保数据的值是正确的 4. 使用getter方法获取属性,使用setter方法设置属性 - 可以在读取属性和修改属性的同时做一些其他的处理 5. 使用getter方法可以表示一些计算的属性 ```python class Person(): def __init__(self, name, age): self.hidden_name = name self.hidden_age = age def get_name(self): return self.hidden_name def set_name(self, name): self.hidden_name = name ... ``` ### 隐藏类中的属性 - 上面的方法已经满足了要求,但是很麻烦,所以python提供了命名方法,对于一个属性,如果将其前面加上双下划线,程序会自动改名为\_类名__属性名 - 但是我们一般不这么用,而是将属性名前面加上单下划线,这是一个约定: ```python class Person(): def __init__(self, name, age): self._name = name self._age = age def get_name(self): return self._name def set_name(self, name): self._name = name ... ``` ### property和setter装饰器 - 我们在上述类中,如果有一个实例需要访问一个属性,需要调用getter方法,需要修改则需要setter方法,比较麻烦,我想要像访问一个属性一样修改/得到属性值 - property装饰器,在getter方法前装饰,这样就可以像访问属性一样调用getter方法,注意:getter方法名需要和属性名相同 - setter装饰器,用于setter方法前装饰,格式为@属性名.setter,注意:setter装饰器必须在property装饰过的属性中使用 ```python class Person(): def __init__(self, name, age): self._name = name self._age = age @property def name(self): return self._name @name.setter def name(self, name): self._name = name; @property def age(self): return self._age @age.setter def age(self, age): self._age = age; p1 = Person('wyy', 16) print(p1.name, p1.age) p1.name = 'zhl' p1.age = 17 print(p1.name, p1.age) ``` - 可以这样直接访问 - 注意:setter一定得在property装饰器装饰过的属性中使用 --- 参考:[阿里云大学Python学习路线](https://edu.aliyun.com/roadmap/python) Last modification:April 6, 2020 © Allow specification reprint Like 如果觉得我的文章对你有用,请随意赞赏