本文最后更新于 2025-01-10T22:20:33+08:00
第六部分 对象 什么是对象? - 对象是内存中专门用来存储数据的一块区域。
- 对象中可以存放各种数据(比如:数字、布尔值、代码)
- 对象由三部分组成:
1.对象的标识(id)
2.对象的类型(type)
3.对象的值(value)
面向对象(oop)
Python是一门面向对象的编程语言
所谓的面向对象的语言,简单理解就是语言中的所有操作都是通过对象来进行的
面向过程的编程的语言
面向过程指将我们的程序的逻辑分解为一个一个的步骤, 通过对每个步骤的抽象,来完成程序
例子:
孩子上学 1.妈妈起床 2.妈妈上厕所 3.妈妈洗漱 4.妈妈做早饭 5.妈妈叫孩子起床 6.孩子上厕所 7.孩子要洗漱 8.孩子吃饭 9.孩子背着书包上学校
面向过程的编程思想将一个功能分解为一个一个小的步骤,我们通过完成一个一个的小的步骤来完成一个程序
这种编程方式,符合我们人类的思维,编写起来相对比较简单
但是这种方式编写代码的往往只适用于一个功能,如果要在实现别的功能,即使功能相差极小,也往往要重新编写代码, 所以它可复用性比较低,并且难于维护
1 2 3 4 5 6 7 8 9 10 11 - 面向对象的编程语言 - 面向对象的编程语言,关注的是对象,而不关注过程 - 对于面向对象的语言来说,一切都是对象 - 例子: 1.孩他妈起床叫孩子上学 - 面向对象的编程思想,将所有的功能统一保存到对应的对象中 比如,妈妈功能保存到妈妈的对象中,孩子的功能保存到孩子对象中 要使用某个功能,直接找到对应的对象即可 - 这种方式编写的代码,比较容易阅读,并且比较易于维护,容易复用。 - 但是这种方式编写,不太符合常规的思维,编写起来稍微麻烦一点
简单归纳一下,面向对象的思想
找对象
搞对象
类(class)
我们目前所学习的对象都是Python内置的对象
但是内置对象并不能满足所有的需求,所以我们在开发中经常需要自定义一些对象
类,简单理解它就相当于一个图纸。在程序中我们需要根据类来创建对象
类就是对象的图纸!
我们也称对象是类的实例(instance)
如果多个对象是通过一个类创建的,我们称这些对象是一类对象
像 int() float() bool() str() list() dict() …. 这些都是类
a = int(10) # 创建一个int类的实例 等价于 a = 10
我们自定义的类都需要使用大写字母开头,使用大驼峰命名法(帕斯卡命名法)来对类命名
类也是一个对象!
类就是一个用来创建对象的对象!
类是type类型的对象,定义类实际上就是定义了一个type类型的对象
示例:定义一个简单的类
1 2 3 4 5 6 7 8 class MyClass (): pass print (MyClass)
使用MyClass创建一个对象 使用类来创建对象,就像调用一个函数一样
1 2 3 4 5 6 7 8 9 mc = MyClass() mc_2 = MyClass() mc_3 = MyClass() mc_4 = MyClass() result = isinstance (mc_2,MyClass) result = isinstance (mc_2,str )
现在我们通过MyClass这个类创建的对象都是一个空对象。也就是对象中实际上什么都没有,就相当于是一个空的盒子 可以向对象中添加变量,对象中的变量称为属性。
1 2 3 4 语法:对象.属性名 = 属性值 mc.name = '孙悟空' mc_2.name = '猪八戒' print (mc_2.name)
使用类创建对象的流程(参考下图)
1.创建一个变量 2.在内存中创建一个新对象 3.将对象的id赋值给变量
类的定义
类和对象都是对现实生活中的事物或程序中的内容的抽象
实际上所有的事物都由两部分构成: 1.数据(属性) 2.行为(方法)
在类的代码块中,我们可以定义变量和函数, 变量会成为该类实例的公共属性,所有的该类实例都可以通过 对象.属性名 的形式访问 函数会成为该类实例的公共方法,所有该类实例都可以通过 对象.方法名() 的形式调用方法
注意: 方法调用时,第一个参数由解析器自动传递,所以定义方法时,至少要定义一个形参!
实例为什么能访问到类中的属性和方法 类中定义的属性和方法都是公共的,任何该类实例都可以访问
一般情况下,属性保存到实例对象中,而方法需要保存到类对象中
尝试定义一个表示人的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class Person : name = 'swk' def say_hello (self ) : print ('你好!我是 %s' %self.name) p1 = Person() p2 = Person() p1.name = '猪八戒' p2.name = '沙和尚' p1.say_hello() p2.say_hello()
类对象的初始化 目前来讲,对于Person类来说name是必须的,并且每一个对象中的name属性基本上都是不同, 而我们现在是将name属性在定义为对象以后,手动添加到对象中,这种方式很容易出现错误
上面这样定义很麻烦
我们希望,在创建对象时,必须设置name属性,如果不设置对象将无法创建,并且属性的创建应该是自动完成的,而不是在创建对象以后手动完成。
在类中可以定义一些特殊方法(魔术方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Person :def __init__ (self,name ): self.name = name def say_hello (self ): print ('大家好,我是%s' %self.name) p1 = Person('孙悟空' ) p2 = Person('猪八戒' ) p3 = Person('沙和尚' ) p4 = Person('唐僧' ) print (p1.name)print (p2.name)print (p3.name)print (p4.name)
类的基本结构 class 类名([父类]) :
公共的属性...
# 对象的初始化方法
def __init__(self,...):
...
# 其他的方法
def method_1(self,...):
...
def method_2(self,...):
...
...
类的练习 定义一个表示dog的类 1 2 3 4 属性:name,age,gender,height ... 方法: jiao(),yao(),run() ...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class Dog : ''' 表示狗的类 ''' def __init__ (self , name , age , gender , height ): self.name = name self.age = age self.gender = gender self.height = height def jiao (self ): ''' 狗叫的方法 ''' print ('汪汪汪~~~' ) def yao (self ): ''' 狗咬的方法 ''' print ('我咬你~~' ) def run (self ): print ('%s 快乐的奔跑着~~' %self.name) d = Dog('小黑' ,8 ,'male' ,30 ) d.name = '阿黄' d.age = -10 d.run()print (d.age)
类的封装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class Dog : ''' 表示狗的类 ''' def __init__ (self , name , age ): self.hidden_name = name self.hidden_age = age def say_hello (self ): print ('大家好,我是 %s' %self.hidden_name) def get_name (self ): ''' get_name()用来获取对象的name属性 ''' return self.hidden_name def set_name (self , name ): self.hidden_name = name def get_age (self ): return self.hidden_age def set_age (self , age ): if age > 0 : self.hidden_age = age
**使用getter方法表示一些计算的属性:**利用get计算矩形面积
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Rectangle : ''' 表示矩形的类 ''' def __init__ (self,width,height ): self.hidden_width = width self.hidden_height = height def get_width (self ): return self.hidden_width def get_height (self ): return self.hidden_height def set_width (self , width ): self.hidden_width = width def set_height (self , height ): self.hidden_height = height def get_area (self ): return self.hidden_width * self.hidden_height
利用下划线进一步的隐藏属性: (用了根没用一样,和改属性名字原理相同,不过是python内置)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Person : def __init__ (self,name ): self.__name = name def get_name (self ): return self.__name def set_name (self , name ): self.__name = name p = Person('孙悟空' ) print (p.__name) p.__name = '猪八戒' print (p._Person__name) p._Person__name = '猪八戒' class Person : def __init__ (self,name ): self._name = name def get_name (self ): return self._name def set_name (self , name ): self._name = name p = Person('孙悟空' )print (p._name)
property装饰器 简单理解就是把 p.set_name(“名字”) 装饰为 p.name = “名字” ,节省两个括号?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Person : def __init__ (self,name,age ): self._name = name self._age = age @property def name (self ): print ('get方法执行了~~~' ) return self._name @name.setter def name (self , name ): print ('setter方法调用了' ) self._name = name @property def age (self ): return self._age @age.setter def age (self , age ): self._age = age p = Person('猪八戒' ,18 ) p.name = '孙悟空' p.age = 28 print (p.name,p.age)
类的继承 继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 class Animal : def run (self ): print ('动物会跑~~~' ) def sleep (self ): print ('动物睡觉~~~' ) class Dog : def run (self ): print ('狗会跑~~~' ) def sleep (self ): print ('狗睡觉~~~' ) def bark (self ): print ('汪汪汪~~~' ) class Dog (Animal ): def bark (self ): print ('汪汪汪~~~' ) def run (self ): print ('狗跑~~~~' ) class Hashiqi (Dog ): def fan_sha (self ): print ('我是一只傻傻的哈士奇' ) d = Dog() h = Hashiqi()class Person (object ): pass print (isinstance (print , object ))
类方法的重写 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Animal : def run (self ): print ('动物会跑~~~' ) def sleep (self ): print ('动物睡觉~~~' )class Dog (Animal ): def bark (self ): print ('汪汪汪~~~' ) def run (self ): print ('狗跑~~~~' ) class A (object ): def test (self ): print ('AAA' )class B (A ): def test (self ): print ('BBB' )class C (B ): def test (self ): print ('CCC' ) c = C() c.test()
super() super() 可以用来动态获取当前类的父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class Animal : def __init__ (self,name ): self._name = name def run (self ): print ('动物会跑~~~' ) def sleep (self ): print ('动物睡觉~~~' ) @property def name (self ): return self._name @name.setter def name (self,name ): self._name = nameclass Dog (Animal ): def __init__ (self,name,age ): super ().__init__(name) self._age = age def bark (self ): print ('汪汪汪~~~' ) def run (self ): print ('狗跑~~~~' ) @property def age (self ): return self._age @age.setter def age (self,age ): self._age = age d = Dog('旺财' ,18 ) print (d.name) print (d.age)
多重继承 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class A (object ): def test (self ): print ('AAA' )class B (object ): def test (self ): print ('B中的test()方法~~' ) def test2 (self ): print ('BBB' ) class C (A,B): pass c = C() c.test()
多态 多态是面向对象的三大特征之一,多态从字面上理解是多种形态 狗:(狼狗、藏獒、哈士奇、古牧 。。。)一个对象可以以不同的形态去呈现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 class A : def __init__ (self,name ): self._name = name @property def name (self ): return self._name @name.setter def name (self,name ): self._name = name class B : def __init__ (self,name ): self._name = name def __len__ (self ): return 10 @property def name (self ): return self._name @name.setter def name (self,name ): self._name = name class C : pass a = A('孙悟空' ) b = B('猪八戒' ) c = C()def say_hello (obj ): print ('你好 %s' %obj.name)def say_hello_2 (obj ): if isinstance (obj , A): print ('你好 %s' %obj.name) say_hello(b) say_hello_2(b) l = [1 ,2 ,3 ] s = 'hello' print (len (b)) print (len (c))
面向对象的三大特征:
1 2 3 4 5 6 封装 - 确保对象中的数据安全 继承 - 保证了对象的可扩展性 多态 - 保证了程序的灵活性
类的总结 类属性 1 2 3 4 5 6 7 8 9 10 11 class A (object ): count = 0 a = A()print (A ,A.count) print (a ,a.count) a.count = 10
实例属性 1 2 3 4 5 6 7 class A (object ): count = 0 def __init__ (self ): self.name = '孙悟空'
实例方法 1 2 3 4 5 6 7 8 9 10 11 12 13 class A (object ): count = 0 def __init__ (self ): self.name = '孙悟空' def test (self ): print ('这是test方法~~~ ' , self)
类方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class A (object ): count = 0 def __init__ (self ): self.name = '孙悟空' def test (self ): print ('这是test方法~~~ ' , self) @classmethod def test_2 (cls ): print ('这是test_2方法,他是一个类方法~~~ ' ,cls) print (cls.count)
静态方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class A (object ): count = 0 def __init__ (self ): self.name = '孙悟空' def test (self ): print ('这是test方法~~~ ' , self) @classmethod def test_2 (cls ): print ('这是test_2方法,他是一个类方法~~~ ' ,cls) print (cls.count) @staticmethod def test_3 (): print ('test_3执行了~~~' )
垃圾回收 就像我们生活中会产生垃圾一样,程序在运行过程当中也会产生垃圾,程序运行过程中产生的垃圾会影响到程序的运行的运行性能,所以这些垃圾必须被及时清理
没用的东西就是垃圾,在程序中没有被引用的对象就是垃圾,这种垃圾对象过多以后会影响到程序的运行的性能,所以我们必须进行及时的垃圾回收,所谓的垃圾回收就是讲垃圾对象从内存中删除
在Python中有自动的垃圾回收机制,它会自动将这些没有被引用的对象删除,所以我们不用手动处理垃圾回收
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class A : def __init__ (self ): self.name = 'A类' def __del__ (self ): print ('A()对象被删除了~~~' ,self) a = A() b = a print (a.name)
特殊方法 特殊方法,也称为魔术方法, 特殊方法都是使用__开头和结尾的 特殊方法一般不需要我们手动调用,需要在一些特殊情况下自动执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 class Person (object ): """人类""" def __init__ (self, name , age ): self.name = name self.age = age def __str__ (self ): return 'Person [name=%s , age=%d]' %(self.name,self.age) def __repr__ (self ): return 'Hello' def __bool__ (self ): return self.age > 17 def __gt__ (self , other ): return self.age > other.age p1 = Person('孙悟空' ,18 ) p2 = Person('猪八戒' ,28 )
模块 模块的创建和引入 模块(module)模块化,模块化指将一个完整的程序分解为一个一个小的模块 通过将模块组合,来搭建出一个完整的程序
不采用模块化,统一将所有的代码编写到一个文件中 .采用模块化,将程序分别编写到多个文件中
模块化的优点: ① 方便开发 ② 方便维护 ③ 模块可以复用!
在Python中一个py文件就是一个模块,要想创建模块,实际上就是创建一个python文件。 注意:模块名要符号标识符的规范。
在一个模块中引入外部模块 ① import 模块名 (模块名,就是python文件的名字,注意不要py)。 ② import 模块名 as 模块别名。
可以引入同一个模块多次,但是模块的实例只会创建一个。
import可以在程序的任意位置调用,但是一般情况下,import语句都会统一写在程序的开头。
在每一个模块内部都有一个__name__属性,通过这个属性可以获取到模块的名字。
__name__属性值为 __main__的模块是主模块,一个程序中只会有一个主模块。主模块就是我们直接通过 python 执行的模块
引入一个叫test_module的模块:
1 2 3 4 import test_module as testprint (__name__)
模块的使用 创建一个模块:m.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 a = 10 b = 20 _c = 30 def test (): print ('test' )def test2 (): print ('test2' )class Person : def __init__ (self ): self.name = '孙悟空' if __name__ == '__main__' : test() test2() p = Person() print (p.name)
主程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import m def test2 (): print ('这是主模块中的test2' ) from m import Person from m import test from m import Person,test from m import * p1 = Person() print (p1) test() test2() from m import test2 as new_test2 test2() new_test2()from m import *
包 包 Package。包也是一个模块 当我们模块中代码过多时,或者一个模块需要被分解为多个模块时,这时就需要使用到包。
普通的模块就是一个py文件,而包是一个文件夹 包中必须要一个一个 init .py 这个文件,这个文件中可以包含有包中的主要内容
引入一个叫hello的包。
1 2 3 4 from hello import a , bprint (a.c)print (b.d)
1 2 3 4 5 # __pycache__ 是模块的缓存文件 # py代码在执行前,需要被解析器先转换为机器码,然后再执行 # 所以我们在使用模块(包)时,也需要将模块的代码先转换为机器码然后再交由计算机执行 # 而为了提高程序运行的性能,python会在编译过一次以后,将代码保存到一个缓存文件中 # 这样在下次加载这个模块(包)时,就可以不再重新编译而是直接加载缓存中编译好的代码即可
python标准库 开箱即用。为了实现开箱即用的思想,Python中为我们提供了一个模块的标准库。 在这个标准库中,有很多很强大的模块我们可以直接使用,并且标准库会随Python的安装一同安装。
sys模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import sys print (sys.argv) print .pprint(sys.path) print (sys.platform) print ('hello' )
pprint 模块
1 2 3 4 5 6 7 8 import pprint pprint.pprint(sys.modules)
os模块
1 2 3 4 5 6 7 8 9 10 import os pprint.pprint(os.environ['path' ]) os.system('notepad' )