前言
五一快乐!
上一篇文章python学习——【第八弹】中,给大家介绍了python中的函数,这篇文章接着学习python中的类和对象。
我们知道,python中一切皆对象。在这篇文章开始之前,我们先了解一下编程界的两大阵营——面向过程和面向对象。
这两个术语我们一定没少听过,那么就简单介绍下什么是面向过程、面向对象,以及两者的区别与联系是什么。
面向过程
面向过程:事物比较简单,可以用线性的思维去解决;举个例子——假如我们的客人来家里做客,我们要请吃饭,想做一道拿手好菜应该分几步呢?我们用线性的思维去考虑,是不是应该分为买菜,洗菜,炒菜这三步呢,用流程图来表示:
面向对象
面向对象:事物比较复杂,使用简单的线性思维无法解释。
我们依然举请客吃饭的例子:如果客人来做客,我们恰好不会做饭,这时可以打开手机点餐APP,通过APP来选择需要点的餐,然后请快递小哥送餐:
区别和联系
通过这两个例子我们发现,面向过程我们需要按照步骤一步一步实现;而通过面向对象,我们只需要创建一个包含实现指定功能和方法、具有指定属性的类
,通过一个个实例化对象调用或者是直接用类来调用这些方法,就能帮助我们实现想要的效果。
面向过程的思维方式主要
关注程序如何执行
,而不是如何被组织和分隔为模块以进行更高层次的抽象和复用。因此,在微观操作方面
,面向过程可能是最适合的方法,因为它强调了严格的顺序和流程控制。
但是,在实现整个程序的过程中
,一些更高级的编程范例(如面向对象)可能更适合于模块化代码并提高代码可重用性和可维护性
。
其实我们在以往的python学习中就接触了很多方法,比如在学习列表中我们会用到append()方法去向列表中添加某一元素,这个appen()方法,就是在列表list类中的一个常用方法:
类的组成与创建
类的组成
类的组成包括:类属性 实例方法 静态方法 类方法
类的创建
类的定义语法: class Class_name: 其中,Class_name是类的名称(类名),由一个或多个单词组成,每个单词首字母大写。
class Class_name:
pass
实例对象的创建
一个类可以创建多个该类的实例对象,每个实例对象的属性值可以不同也可以相同,并且实例对象的权限是最大的。创建完成实例对象,就可以通过这个实例对象调用实例方法或者类属性等。
实例对象的创建语法:实例对象名=类名(参数)
如果类内没有传递静态变量,这里实例对象的创建就不需要参数传递。(当实例对象被创建时,Python会自动为它分配空间,并调用类的__init__方法来执行初始化操作。如果没有定义传递参数,就不需要传递任何参数。)
class Student:
pass
stu1=Student(参数1,参数2,参数3,。。。)
stu2=Student(参数1,参数2,参数3,。。。)
stuN=Student(参数1,参数2,参数3,。。。)
实例化对象的id值转换成十六进制和value值相同,这里:stu1id值:140203633998736 转换成十六进制等于 其value值 7f83b3ccfb90
stu1=Student(‘tom’,20) #在init方法中我们传入了name age两个参数,这里创建的实例对象的参数也是两个
print(id(stu1),type(stu1)) #140203633998736 <class ‘main.Student’>
print(stu1) #<main.Student object at 0x7f83b3ccfb90> id转换成十六进制和输出的stu1的值是相同的
类属性
类属性:类中方法外的变量都叫做类属性,类属性被该类的所有对象共享。
类属性的调用方法:
1:可以使用实例对象调用,语法是 实例对象名.属性
2:可以直接用类调用,语法是 类名.类属性
class Place:
# 类属性
place1='山东'
place2='河南'
#pl1和pl2分别为该类的实例对象
pl1=Place()
pl2=Place()
print('----------类属性的使用------------------\n')
#实例对象调用
print('出生地1:',pl1.place1,id(pl1.place1))
print('出生地2:',pl1.place2,id(pl1.place2))
print('直接被类调用:',Place.place1,Place.place2)
'''
出生地1: 山东 140018104483248
出生地2: 河南 140018103789008
直接被类调用: 山东 河南
'''
print('\n----------在类外使用类改变类属性-------\n')
# 类属性:place1和place2 被该类的所有实例对象(这里是pl1和pl2)所共享,
#因此在类外将类属性改变后,用该类的所有实例对象调用该类属性时,类指针指向的地址都是类属性改变后的地址
Place.place1='河北'
print('出生地1:',pl1.place1,id(pl1.place1))
print('出生地2:',pl2.place1,id(pl2.place1))
'''
出生地1: 河北 140314679194608
出生地2: 河北 140314679194608
'''
我们看到在类外改变类属性后,利用实例对象再次调用这一类属性时,打印出来的是类属性改变后的值
,我们来看一下内存图:
可以直观的看到,在每个实例对象中都存有一个类指针,指向类,那么当我们改变某个类属性指向的地址时,实例对象调用该属性时打印出来的就是类属性改变后的内存地址。
类中的初始化方法
Python中的初始化方法是在创建对象时最先调用的一个方法,用于对对象的属性进行初始化。通常情况下,初始化方法被实现为 __ init__() 方法。它的格式是 def__init__(self):
其中,方法名是由init (initialize的缩写,初始化的意思)加左右两边的双下划线组成。
在进行初始化方法时,须要传入一个参数 self(self是约定俗成的变量名,用于表示实例对象本身。虽然可以选择其他名称作为self参数,一般遵循这个约定,以确保代码易于阅读和理解。), 在python的类中 self代表实例本身,具体来说,是该实例方法的内存地址
;在类的方法中(如__ init__),第一个参数永远都是self,表示创建的类的实例本身,而不是类本身。
每当进行类的实例化时,初始化方法会被自动执行,举个例子:
可以看到:我们只是创建了一个实例对象,并没有调用 init 方法,它就自动执行了。利用这个特性,我们通常会在 初始化方法 里完成类属性初始值的设置。
class Student :
#类属性
place='山东'
school='大学'
# 初始化方法
def __init__(self,name,age):
self.name=name #self.name 称为实例属性 进行一个赋值操作 将局部变量的name的值赋给实例属性
self.age=age
我们在初始化方法中传入了name,age两个参数,这时它们还只是局部变量,要想能够被实例对象调用,需要在初始化方法中将局部变量分别赋给实例属性
,这里的实例属性是self.name, 当然也可以是self.别名,只是我们习惯上用局部变量的名字,这样也具有一定的可读性。
当我们创建类的实例对象时传入了参数,那么就要在类体内进行初始化方法,并传入相关参数。
这里我们简单了解下python中得self参数:
1.self只有在类的方法中才会有 , 其他函数或方法是不必带self的。
2.在调用时不必传入相应的参数。
3.在类的方法中(如__init__) , 第一参数永远是self , 表示创建的类实例本身 , 而不是类本身。
4.可以把对象的各种属性绑定到self。
5.self代表当前对象的地址。self能避免非限定调用造成的全局变量。
6.self不是python的关键字, 也可以用其他名称命名 , 但是为了规范和便于读者理解 , 推荐使用self。
7:python中的self等价于C++中的self指针和Java、C#中的this参数。
8:如果不加self , 表示是类的一个属性(可以通过"类名.变量名"的方式引用), 加了self表示是类的实例的一个属性(可以通过"实例名.变量名"的方式引用)。
实例方法
在类中定义的函数叫做方法,相当于类外的函数,该方法可以具备一定的功能,调用后执行。
实例方法最大的特点就是,它最少也要包含一个 self 参数,用于绑定调用此方法的实例对象(Python 会自动完成绑定)。
实例化方法的调用:
1:使用实例对象调用: 实例对象名.方法名()
2:使用类调用: 类名.实例方法名(实例对象名)
class Student:
place='山东' #类属性 直接写在类里的变量 叫做类属性
school='大学'
# 初始化方法
def __init__(self,name,age):
self.name=name
self.age=age
# 实例方法 定义在类外面的函数叫做函数;定义在类里面的函数叫做方法
# 其中info()括号中可以不写东西,但是默认是存在self的,习惯上写上self
def info(self):
print('我的名字叫:',self.name,'年龄是:',self.age)
def eat(self):
print('吃东西')
def drink():
print('喝水')
# 创建实例对象
stu1=Student('tom',20)
print('\n----------------使用实例对象调用实例方法------------\n')
# 创建完成实例对象,就可以通过这个实例对象调用实例方法 对象名.方法名
stu1.eat()
stu1.info()
stu1.drink()
'''
吃东西
我的名字叫: tom 年龄是: 20
喝水
'''
print('\n-----------------通过Student类来调用实例方法-----------\n')
# 或者是通过Student类进行实例方法的调用 类名.方法名(对象名)
Student.eat(stu1)
Student.info(stu1)
Student.drink()
'''
吃东西
我的名字叫: tom 年龄是: 20
喝水
'''
如果在实例方法中没有写入任何参数时,在用类调用该实例方法时不需要传入实例对象;如果传入会抛出 TypeError: drink() takes 0 positional arguments but 1 was given 错误
类方法
类方法 :在类内使用装饰器 @classmethod 修饰的方法 ,使用类名直接访问。
Python 类方法和实例方法相似,它最少也要包含一个参数,只不过类方法中通常将其命名为 cls,Python 会自动将类本身绑定给 cls 参数(注意,绑定的不是类对象)。也就是说,我们在调用类方法时,无需显式为 cls 参数传参。
类方法的调用:
1:使用类名: 类名.类方法名()
2:使用实例对象:实例对象名.类方法名()
# 类方法的使用
class Staff:
# 类方法
@classmethod
def class_method(cls):
print('我是一个类方法')
staff1=Staff()
staff2=Staff()
print('------------类方法的使用-----------\n')
Staff.class_method()
print('----------实例对象调用类方法------\n')
staff2.class_method()
如果没有 @classmethod,则 Python 解释器会将class_method() 方法认定为实例方法,而不是类方法。
静态方法
静态方法:其实就是我们学过的函数,和函数唯一的区别是,静态方法定义在类这个空间(类命名空间)中,而函数则定义在程序所在的空间(全局命名空间)中,即类体外。
静态方法没有类似 self、cls 这样的特殊参数,因此 Python 解释器不会对它包含的参数做任何类或对象的绑定。也正因为如此,类的静态方法中无法调用任何类属性和类方法。
静态方法 :使用@staticmethod修饰的方法, 使用类名直接访问。
静态方法的调用:
1:使用类名: 类名.静态方法名()
2:使用实例对象:实例对象名.静态方法名()
# 静态方法的使用
class Workers:
@staticmethod
def static_method():#静态方法中没有默认参数
print('我是一个静态方法')
worker1=Workers()
print('-----------使用类调用静态方法-----------\n')
Workers.static_method()
print("----------使用实例对象调用静态方法-----------\n")
worker1.static_method()
总结
在实际编程中,几乎不会用到类方法和静态方法,因为我们完全可以使用函数代替它们实现想要的功能,但在一些特殊的场景中(例如工厂模式中),还是会使用类方法和静态方法。
每篇一语
听一千遍别人的故事,不如做一件自己的事情。
如有不足,感谢指正!