解锁面向对象编程:Python 类与对象详解

🏠大家好,我是Yui_💬
🍑如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
🚀如有不懂,可以随时向我提问,我会全力讲解~
🔥如果感觉博主的文章还不错的话,希望大家关注、点赞、收藏三连支持一下博主哦~!
🔥你们的支持是我创作的动力!
🧸我相信现在的努力的艰辛,都是为以后的美好最好的见证!
🧸人的心态决定姿态!
💬欢迎讨论:如有疑问或见解,欢迎在评论区留言互动。
👍点赞、收藏与分享:如觉得这篇文章对您有帮助,请点赞、收藏并分享!
🚀分享给更多人:欢迎分享给更多对编程感兴趣的朋友,一起学习!

python从设计之初就是一门面向对象的语言,它提供一些语言特性支持面向对象编程。那么第一个问题就是什么是面向对象。

文章目录

  • 1. 什么是面向对象
  • 2. 面向对象术语介绍
  • 3. 类的定义与使用
  • 3.1 类的定义
  • 3.2 self用法解释
  • 3.3 类属性和实例属性
  • 3.3.1 类属性
  • 3.3.2 实例属性
  • 3.4 实例方法、类方法
  • 3.4.1 实例方法
  • 3.4.2 类方法
  • 4.总结
  • 1. 什么是面向对象

    面向对象( Object-Oriented Programming)是现代编程语言都存在的一种编程方式,如果你使用过C语言会发现,每当需要实现一个功能时都需要创建一个一个的函数来实现,这是面向过程。如果你使用过C++或者JAVA就会发现,当实现一个功能时,会把这个功能需要的属性和函数抽象出来封装成一个整体,程序员再对这个整体进行操作,这个整体也就叫做类,类实例出的东西叫做对象。
    下面贴上维基百科)的解释:
    面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是种具有对象概念的编程典范,同时也是一种程序开发的抽象方针。它可能包含数据、特性、代码与方法。对象则指的是类(class)的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性,对象里的程序可以访问及经常修改对象相关连的数据。在面向对象程序编程里,计算机程序会被设计成彼此相关的对象。
    面向对象程序设计可以看作一种在程序中包含各种独立而又互相调用的对象的思想,这与传统的思想刚好相反:传统的程序设计主张将程序看作一系列函数的集合,或者直接就是一系列对电脑下达的指令。面向对象程序设计中的每一个对象都应该能够接受数据、处理数据并将数据传达给其它对象,因此它们都可以被看作一个小型的“机器”,即对象。目前已经被证实的是,面向对象程序设计推广了程序的灵活性和可维护性,并且在大型项目设计中广为应用。此外,支持者声称面向对象程序设计要比以往的做法更加便于学习,因为它能够让人们更简单地设计并维护程序,使得程序更加便于分析、设计、理解。反对者在某些领域对此予以否认。
    当我们提到面向对象的时候,它不仅指一种程序设计方法。它更多意义上是一种程序开发方式。在这一方面,我们必须了解更多关于面向对象系统分析和面向对象设计(Object Oriented Design,简称OOD)方面的知识。许多流行的编程语言是面向对象的,它们的风格就是会透由对象来创出实例。

    2. 面向对象术语介绍

    在正式具体介绍面向对象技术前,我们需要先了解一些面向对象的术语,以便在后续内容中能够明白对应的意思。

  • 类:用于描述具体相同属性和方法的对象的集合。类定义了集合中每个对象共有的属性和方法。对象是类的实例。
  • #基本语法
    class MyClass:
    	#类的属性
    	#类的方法
    
  • 类变量(类属性):类变量在整个实例化的对象中是公用的。类变量定义在类中,且在方法之外。类变量通常不能作为实例变量使用。类变量也称为类属性(类似于Java的static的)。
  • class Person:
    	species = "Human" #类属性
    print(Person.species) #访问类属性
    
  • 数据成员:实例属性是对象独有的,通过self关键字定义
  • 方法重写:如果从父类继承的方法不能满足子类的需求,就可以对可以对其进行改写,这个过程称为方法的覆盖(Override),也称为方法的重写。
  • 实例变量(实例属性):定义在方法中的变量只作用于当前实例的类。
  • class Person:
    	def __init__(self,name,age):
    		self.name = name #实例属性
    		self.age = age #实例属性
    person1 = Person('Yui',17)
    person2 = Person('Yamada',14)
    print(person1.name) #输出:Yui
    print(person2.name)
    
  • 封装(Encapsulation):对外部世界隐藏对象的工作细节。
  • 继承(Inheritance):一个派生类(derived class)继承基类(base class)的字段和方法。继承允许把一个派生类的对象作为一个基类对象对待,以普通类为基础建立专门的类对象。
  • 多态(Polymorphism):对不同类的对象使用相同的操作。
  • 实例化(Instance):创建一个类的实例、类的基础对象。
  • 方法:类中定义的函数。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
    python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类、派生类可以覆盖基类中的任何方法、方法中可以调用基类中的同名方法。
    对象可以包含任意数量和类型的数据。
  • 3. 类的定义与使用

    3.1 类的定义

    定义一个类:

    class Person(object):
    	#属性
    	species = "Human" #类属性
    	#初始化方法
    	def __init__(self,name,age):
    		self.name = name #实例属性
    		self.age = age
    	#方法
    	def introduce(self):
    		print(f'My name is {self.name}, and I am {self.age} years old.')
    

    从这段代码可以看出,定义类时需要使用到关键字class,注意在给类取名时应该做到每个单词的首字母大写,其它字母小写。可以看到Person后面紧接着object代表着该类继承于object,我们要知道所有类都继承自object,所以这个object继承是可以省略的。
    注意,无论是类属性还是类方法,对应类来说,它们都不是必须的,可以有也可以没有。另外,python类中的属性和方法所在的位置也是任意的,也就是说,它们是没有固定的前后顺序的。
    关于__init__、self,如果你又学过C++/java可以把它们分别理解为构造函数和this指针。关于它们的具体介绍会在文章后面介绍。

    3.2 self用法解释

    了解完类的定义就可以简单地使用类了。

    class MyClass:
    	i = 111
    	def f(self):
    		return 'hello wrold'
    use_class = MyClass() #类的实例化
    print('调用类的属性:',use_class.i)
    print('调用类的方法:',use_class.f())
    

    关于self
    在上面的示例中,类中定义了应该f()方法中带有了应该self参数,可是我们并没有传入参数,那么它有什么作用呢?
    self 是类中的实例方法的第一个参数,用于指代当前对象的引用。通过 self,可以访问当前对象的属性和方法。虽然名字不固定,但通常约定俗成地使用 self
    等价的代码:

    MyClass.f()
    #等价于:
    MyClass.f(MyClass)
    

    那么为什么需要self的存在呢?
    它的作用主要就是用来标识特定的对象的,在学习面向对象的时候,许多老师都会把类比作成一张图纸(你可以理解为房屋设计的图纸),利用这个图纸,你可以设计出许多的房屋(也就是类对象),每个房子的长相都是类似的(都有相同的类变量和类方法),但是尽管它们一样,但是它们的主人是不一样的,也就导致了这些房间的门锁不同。
    self它就相当于每个房间的门钥匙,可以保证每个房间的主人仅能进入自己的房间(每个类对象只能调用自己的类对象和类方法)。
    就像前面的代码:

    MyClass.f()
    #等价于:
    MyClass.f(MyClass)
    #保证每个类对象只能调用自己的类对象和类方法
    

    同一个类可以产生多个对象,当某个对象调用类方法时,该对象会把自身的引用作为第一个参数自动传给该方法,也就是说,python会自动绑定类方法的第一个参数指向该方法的对象。这样的话,python解释器就知道到底要操作哪个对象的方法了。
    因为,self编译器会自动调用,所以在代码书写的过程中,不需要显示写出来。

    class MyClass:
        def __init__(self):
            print('我是构造方法')
        def run(self):
            print(self,'我是run方法')
    
    test1 = MyClass()
    test1.run()
    test2 = MyClass()
    test2.run()
    

    打印结果:`

    我是构造方法
    <__main__.MyClass object at 0x000001FF12F37380> 我是run方法
    我是构造方法
    <__main__.MyClass object at 0x000001FF12F373B0> 我是run方法
    

    从打印结果来看,这两个实例出的对象确实是不同的,两个对象打印的self是不同的。
    run()中的self代表该方法的调用者,谁调用该方法,那么self就代表谁。

    3.3 类属性和实例属性

    在前面的内容里。我们简单的了解了下类属性和实例变量。
    无论是类属性还是类方法,都是无法像普通变量或者函数那样,在类外直接使用它们。因为类中的方法和属性都被封装起来了。类就是一个独立的空间,类属性就是类中定义的变量,类方法也是累中定义的函数
    通过总结,我们可以吧类属性分为以下3种类型。

    1. 类体中、所有函数之外:此范围定义的变量,称为类属性或类变量。
    2. 类体中,所有函数内部:以self.变量名的方式定义的变量,称为实例属性或者实例变量。
    3. 类体中,所有函数内部:以self=变量名的方式定义的变量,称为局部变量。

    此外还有实例方法、静态方法和类方法,在后续内容中出现。

    3.3.1 类属性

    类属性是在类中,但是在各个类方法外定义的变量。

    #类变量演示
    
    class Person:
        name = '小明'
        age = 18
        weight = 70
    
    if __name__ == '__main__':
        print(Person.name)
        print(Person.age)
        print(Person.weight)
    
    #打印结果:
    '''
    小明
    18
    70
    '''
    

    可以看到,我们并没有实例化出对象,但是这些变量依旧可以正常访问。
    这一现象说明了,类变量是作为公共资源存在的,为所有实例化出的对象所公用,所有即使不实例化出对象依旧可以访问类属性。
    改写代码:

    class Person:
        name = '小明'
        age = 18
        weight = 70
    
    if __name__ == '__main__':
        print(Person.name)
        Person.name = "小红"
        print(Person.name)
    '''
    小明
    小红
    '''
    

    可以看到类名不仅可以调用类变量,也可以修改它的值。
    值得一提的还有:除了可以通过类名访问类变量外,还可以动态地为类和对象添加类变量。如下:

    class Person:
        name = '小明'
        age = 18
        weight = 70
    
    if __name__ == '__main__':
        print(Person.name)
        Person.name = "小红"
        print(Person.name)
        Person.xixi = 100
        print(Person.xixi)
    

    3.3.2 实例属性

    实例属性指的是在任意类方法内部,以self.变量名的方法定义的变量,特点在于作用于调用方法的对象。
    注意:实例变量只能通过对象访问,无法通过类名访问。

    class Person:
        def __init__(self):
            self.name = 'yui'
            self.age = 18
        def say(self):
            self.test = 100
    
    if __name__ == '__main__':
        p = Person()
        print(p.name)
        print(p.age)
        #print(p.test) 报错
        p.say()
        print(p.test)
    '''
    yui
    18
    100
    '''
    

    由于init()函数在创建类对象时会自动调用,而say()方法需要我们手动调用。因此造成了直接调用name和age没有问题,而在调用了say()函数前,test是无法调用的。

    3.4 实例方法、类方法

    和类属性一样,类方法也可以进行更细致的划分,具体可分为类方法、实例方法和静态方法。

    和类属性的分类不同,对于初学者来说,区分这 3 种类方法是非常简单的,即采用 @classmethod 修饰的方法为类方法;采用 @staticmethod 修饰的方法为静态方法;不用任何修改的方法为实例方法。

    3.4.1 实例方法

    默认情况下,在类中定义的方法都是实例方法。

    class Person:
        def __init__(self):
            self.name = 'yui'
            self.age = 18
        def say(self):
            print("%s is %d years old" % (self.name, self.age))
    
    if __name__ == '__main__':
        p = Person()
        p.say()
    #yui is 18 years old
    

    注意:实例方法的参数最少也要包含一个self参数。

    3.4.2 类方法

    Python 类方法和实例方法相似,它最少也要包含一个参数,只不过类方法中通常将其命名为 cls,Python 会自动将类本身绑定给 cls 参数(注意,绑定的不是类对象)。也就是说,我们在调用类方法时,无需显式为 cls 参数传参。
    和 self 一样,cls 参数的命名也不是规定的(可以随意命名),只是 Python 程序员约定俗称的习惯而已。
    和实例方法最大的不同在于,类方法需要使用@classmethod修饰符进行修饰,例如:

    class Person:
        def __init__(self):
            pass
        @classmethod
        def say(cls):
            print('hello world')
    if __name__ == '__main__':
        Person.say()
    '''
    hello world
    '''
    

    4.总结

    本篇博客主要讲解了,python中的一些特性,如self、类属性和实例属性、类方法和实例方法。对于python的类和对象并未完全讲完,如static方法,继承与多态等等,在下期我会更新出python类和对象的下一部分。

    作者:Yui_

    物联沃分享整理
    物联沃-IOTWORD物联网 » 解锁面向对象编程:Python 类与对象详解

    发表回复