python学习之【类和对象】

前言

五一快乐!
上一篇文章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()

总结

在实际编程中,几乎不会用到类方法和静态方法,因为我们完全可以使用函数代替它们实现想要的功能,但在一些特殊的场景中(例如工厂模式中),还是会使用类方法和静态方法。

每篇一语

听一千遍别人的故事,不如做一件自己的事情。

如有不足,感谢指正!

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
xiaoxingxing的头像xiaoxingxing管理团队
上一篇 2023年5月26日
下一篇 2023年5月26日

相关推荐