Python面向对象编程基础:类、实例与核心语法详解

小满
小满
发布时间:2026-10-12 | 3人浏览过
原创

本文深入解析Python面向对象编程核心概念,从“一切皆对象”出发,通过实例阐述类与实例的关系。详细讲解类的基本语法、新旧式类的区别(Python 2.2引入type统一),以及__init__、__new__和__del__等关键特殊方法的用法与注意事项,帮助开发者掌握Python类的高级特性。

在着手撰写Python面向对象编程的内容时,我曾感到十分纠结。由于Python中面向对象涉及的知识点繁多,若要彻底讲透,似乎需要以面向对象的思想重新梳理之前的所有内容。鉴于这个话题覆盖面广,经过反复权衡,本文仅选取重点内容进行讲解,其余部分需读者自行拓展学习。

在此声明,本文基于Python 2.7版本编写,不同版本间可能存在差异。

在正式讲解前,我们先通过一段代码思考一个问题:

为什么我只为变量a赋值,就能调用一些我并未定义的方法?

部分读者可能会回答:因为a此时是一个字符串对象,自然可以使用字符串内置的方法,这些方法是Python预先定义好的。

那么,另一个问题是:Python是如何判断它属于字符串对象的?

在深入探讨之前,请记住一个核心概念:在Python中,一切皆对象,而所有对象均由类创建。

那么,究竟什么是类?这里举一个生活中的例子。

假设我在街上行走,迎面遇到一个仇人。我想教训他,但考虑到力的相互作用,打他我的拳头也会疼。此时,我注意到路边有一块大小形状合适的石头。在不考虑法律后果的前提下,这是一个理想的选择。于是,我捡起石头对仇人实施了攻击(此处为比喻,请勿模仿),然后低调离开。

在这个过程中,我们是如何识别出那块物体是石头的?

因为它具备石头的外观特征。

我们又是如何知道石头可以用来砸人?

因为石头具有坚硬的特性。

我们又是如何知道石头是坚硬的?

这源于过往的经验,比如小时候长辈的教导。

由此得出结论:我们之所以知道某物是什么、具备何种功能,是因为脑海中已存在该物体的概念。这个概念可能来自长辈传授,也可能通过自身实验总结得出。这类似于科学家对“黑洞”等概念的研究与总结过程。

若将上述“用石头打人”的例子转化为代码,实现如下:

class Stone(object):  # 我创建一个叫Stone的类

  def attack(self):
    print '把头伸过来,我给你加个buff'

a = Stone()  # 我用类创建了一个对象,也称为类的实例化
a.attack()   # 我使用这个对象的方法

通过这种方式,我们便实现了所需的功能。

如果我们尝试创建其他对象:

显然,Python并未为其他对象提供attack方法,因此无法调用。

类仅是一种抽象定义,而实例则是具体的对象。两者的区别如同我脑海中的石头概念与我手中实际的石头,只有后者真实存在。此处无需探讨唯心主义等哲学问题。

至此,类与对象之间的关系应已清晰。部分同学可能会问:Python中的类是否都是预先写好的?是否存在让Python自动生成类并在特定时刻使用的方法?如果这一设想实现,其效果将接近人类的学习能力,这也触及了人工智能的核心概念。虽然目前尚无法实现真正的人工智能,但编写智能程序可能是程序员的终身追求。

在理解类与实例化之后,我们来看类的基本语法。

首先,与定义函数使用的def关键字类似,class是定义类的关键字。

紧接着是类名,可自定义,但需避免与Python内置关键字冲突。建议同时避开Python的内建类型名称,如str、int等。规范的命名应遵循“驼峰命名法”,例如MyClass,即每个单词首字母大写。

随后是一个括号,其中的参数用于继承,通常继承自object,表示这是一个新式类。你可能见过没有括号的写法,那是经典类的写法。

示例如下:

class NewClass(object):
  pass

class OldClass:
  pass

New = NewClass()  # 创建一个新式类的实例
Old = OldClass()  # 创建一个经典类的实例

这就是类的基本语法。虽然这还不够完整,但在深入之前,我想先讲解新式类与经典类的区别。

在此,我们先打印两个变量的类型:

print type(New)
print type(Old)

可以看到两者的输出结果不同。

在Python 2.2之前的版本中,仅存在经典类这一种写法,当时类与类型尚未合并。

类是类对象,实例是实例对象,两者之间没有任何关联。

这句话的具体含义可通过代码观察:

print type(OldClass)
print type(Old)

我们可以发现输出结果较为模糊。在经典类中,无论属于哪个类,统一归类为“类”类型;实例则统一为“实例”类型,无法区分其由哪个类创建。也就是说,当时的类型用classobj和instance代表了所有类和实例,无论具体是哪个类或由其创建的实例。

由于此类信息过于匮乏,且类与类型之间关系混乱,Python 2.2引入了新式类,并实现了类与类型的统一。

print type(NewClass)
print type(New)

类的类型是type?type返回的对象能否像类一样创建新对象?

总结来说:在新式类中,所有类对象都是type的实例。而不同的类对象能够创建出对应的实例。

class NewClass(object):
  def __init__(self, val):
    self.val = val

New = NewClass(123)  
b = type(New)(321) # 对实例来说type返回的是类对象,我又可以用类对象来和创建新的实例
print b.val

构造器方法

通常理解,类中的函数即为方法。方法主要分为三类:实例方法,需实例化后调用,第一个参数通常为self,代表实例本身;类方法,第一个参数为cls,代表类本身;静态方法,即普通函数,对参数无特殊要求。

1. __init__(self [,arg1,....]):

当类被调用进行实例化时,Python会自动调用类中的构造函数(如果存在)。在构造函数中,可执行各种初始化操作,最常见的是创建实例属性。

Python在实例化时会检查是否实现了__init__方法。若未实现,则不对实例进行任何操作并返回对象;若已实现,则自动调用该方法,并自动传入self。这意味着在实例化传参时,我们无需理会self,直接传递给后续参数即可。

讲到属性,必须明确什么是属性。属性对象更像是一个变量,大多数对象(不包括Python的内置类型)都可以拥有属性,例如函数。

def Test():
  pass

Test.a = 123
print Test.a

因为函数本身也是一个对象。

属性在类中表现为一个变量,例如:

class NewClass(object):
  a = 123

print NewClass.a

当然,得益于Python的特性,我们可以在运行过程中为某个对象添加属性,而无需在类定义初期就写定。

注意,该方法应返回None,即通常不需要return任何对象,保持默认返回即可。

2. __new__(cls [,arg1,....]):

这也是一个构造器方法,属于类方法,在对Python的不可变数据类型进行继承扩展时较为常用。

以下是一段参考代码示例:

class RoundFloat(float):
  def __new__(cls, val):
    return super(RoundFloat, cls).__new__(cls, round(val, 2))

a = RoundFloat(3.14159)
print a

解构器方法

__del__(self [,arg1,....])

该方法将在对象的所有引用被清除后执行,例如:

class Test(object):

  def __del__(self):
    print '我被干掉了,兄弟们为我报仇!'

a = Test() # 创建了一个对象
b = a  # b又引用了a
c = b  # c又引用了b,现在 a 所指向的对象有3次引用,相当有三条命
del a  # 干掉一条命
del b  # 又干掉
del c  # 听说你有3条命?全部干掉!

注意,这里仅输出了一次,说明直到最后引用计数归零时才执行删除。需注意以下几点:

1. 调用del并不意味着立即删除某个对象,仅是减少引用计数。

2. 若存在循环引用或其他原因导致实例引用未释放,该对象的__del__()可能永远不会被执行。

3. __del__()中未捕获的异常会被忽略(因为__del__()中使用的某些变量可能已被删除)。不要在__del__()中执行与实例无关的操作。

4. 一般情况下无需实现此方法,因为存在一定风险。

5. 若定义了__del__,且实例处于循环引用中,垃圾回收器将不会终止该循环——你需要自行显式调用del。

6. 若继承了父类,且父类中也定义了__del__,务必记得调用父类的__del__()。否则可能导致父类中的某些清理方法未被调用,引发不可预料的错误。

以上关于Python面向对象及类基本语法的讲解到此结束,希望能对大家有所帮助,欢迎支持本站。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表