如何理解 Python 中的面向对象编程?

我们利用.init()初始化和定义了实例,我们还可以在这个方法或其他实例方法中,通过给某个数据属性赋值的方式改变属性值:

class MyClass:

… def init(self, arg_1, arg_2, arg_3):

… self.x = arg_1

… self._y = arg_2

… self.__z = arg_3

现在MyClass有三个数据属性:

  • .x可以获取arg_1的值

  • …_y可以获取arg_2的值

  • …__ z可以获取arg_3的值

我们可以利用Python的解包机制,用更紧凑的形式编写这段代码:

class MyClass:

… def init(self, arg_1, arg_2, arg_3):

… self.x, self._y, self.__z = arg_1, arg_2, arg_3

属性名称中的下划线(_)是为了表明这些属性是“私有”属性:

  • 开头没有下划线的属性(比如.x)通常可供对象外部的调用和修改。

  • 开头拥有一个下划线的属性(比如._y)通常也可以从对象外部调用和修改。然而,下划线是一种惯用的标志,即该类的创建者强烈建议不要使用该变量。应该仅通过类的功能成员(比如方法和属性)调用和修改该变量。

  • 开头拥有双下划线的属性(比如.__ z)将在名字修饰过程中被改名(在本例中它将被改名为._MyClass__z)。你也可以通过这个新名称从对象外部调用和修改它们。但是,我强烈反对这种做法。应该尽通过类的功能成员以其原始名称进行调用和修改。

Python对象的数据属性通常存储在名为.__ dict__的字典中,它也是对象的属性之一。但是,你也可以将数据属性存储在其他地方。我们可以直接访问__dict__,或利用Python的内置函数vars()获取.__ dict__:

a = MyClass(2, 4, 8)

vars(a)

{‘x’: 2, ‘_y’: 4, ‘_MyClass__z’: 8}

a.dict

{‘x’: 2, ‘_y’: 4, ‘_MyClass__z’: 8}

名字修饰过程把键’__z’变成了’_MyClass__z’。

我们可以把.__ dict__当成普通的Python字典使用。

获取和修改与数据属性关联的值的常规方法如下:

a.x

2

a._y

4

a.__z

Traceback (most recent call last):

File “”, line 1, in

AttributeError: ‘MyClass’ object has no attribute ‘__z’

a.x = 16

a.x

16

vars(a)

{‘x’: 16, ‘_y’: 4, ‘_MyClass__z’: 8}

请注意,我们无法访问.__ z,因为.__ dict__没有键’__z’。

实例方法


下面,我们来创建两个实例方法:

  • .set_z():修改.__ z。

  • …get_z():返回.__ z的值。

请记住,每个实例方法的第一个参数(按照约定名为self)引用对象本身,但我们无需在调用方法时指定这个参数:

class MyClass:

… def init(self, arg_1, arg_2, arg_3):

… self.x, self._y, self.__z = arg_1, arg_2, arg_3

… def set_z(self, value):

… self.__z = value

… def get_z(self):

… return self.__z

b = MyClass(2, 4, 8)

方法.get_z()和.set_z()提供了传统的检索和修改.__ z值的方法:

b.get_z()

8

b.set_z(16)

vars(b)

{‘x’: 2, ‘_y’: 4, ‘_MyClass__z’: 16}

你也可以在.get_z()和.set_z()中添加其他功能,例如检查数据的有效性。这种方法实现了面向对象编程中的一个主要概念:封装。

属性


还有一种方法(一种更Python的方式)访问和修改数据属性是使用属性。属性封装了一系列方法:getter、setter和deleter,但其行为与普通的数据属性相同。

下面的代码实现了属性.z,其中还包含.get_z()和.set_z()的功能:

class MyClass:

… def init(self, arg_1, arg_2, arg_3):

… self.x, self._y, self.__z = arg_1, arg_2, arg_3

… @property

… def z(self):

… return self.__z

… @z.setter

… def z(self, value):

… self.__z = value

b = MyClass(2, 4, 8)

如下,我们利用相应的属性.z来访问和修改数据属性.__ z:

b.z

8

b.z = 16

vars(b)

{‘x’: 2, ‘_y’: 4, ‘_MyClass__z’: 16}

这段代码比上述示例更精简优雅。

类与静态方法


除了实例方法和属性之外,类还可以拥有类方法和静态方法。

下面让我们为MyClass添加三个方法:

class MyClass:

… def init(self, arg_1, arg_2, arg_3):

… self.x, self._y, self.__z = arg_1, arg_2, arg_3

… def f(self, arg):

… print(‘instance method f called’)

… print(f’instance: {self}')

… print(f’instance attributes:\n{vars(self)}')

… print(f’class: {type(self)}')

… print(f’arg: {arg}')

… @classmethod

… def g(cls, arg):

… print(‘class method g called’)

… print(f’cls: {cls}')

… print(f’arg: {arg}')

… @staticmethod

… def h(arg):

… print(‘static method h called’)

… print(f’arg: {arg}')

c = MyClass(2, 4, 8)

方法.f()是一个实例方法。实例方法的第一个参数是对象本身的引用。这些方法可以利用self访问对象,利用vars(self)或self.__dict__访问对象的数据属性,还可以利用type(self)或self.__class__访问对象对应的类,而且它们还可以拥有自己的参数。

方法.g()的开头包含修饰器@classmethod,表明这是一个类方法。每个类方法的第一个参数都会指向类本身,按照约定该参数名为cls。与实例方法的情况一样,我们不需要明确提供与cls对应的参数。而类方法可以利用cls和自己的参数访问类本身。

方法.h()的开头包含修饰器@staticmethod,表明这是一个静态方法。静态方法只能访问自己的参数。

Python中常见的调用实例方法的方法如下:

c.f(‘my-argument’)

instance method f called

instance: <main.MyClass object at 0x7f32ef3def98>

instance attributes:

{‘x’: 2, ‘_y’: 4, ‘_MyClass__z’: 8}

class: <class ‘main.MyClass’>

arg: my-argument

通常,我们应该直接通过类(而不是实例)调用类方法和静态方法:

MyClass.g(‘my-argument’)

class method g called

cls: <class ‘main.MyClass’>

arg: my-argument

MyClass.h(‘my-argument’)

static method h called

arg: my-argument

请记住,我们不需要传递类方法的第一个参数:与cls相对应的参数。

但是,我们可以像下面这样调用类方法和静态方法:

c.g(‘my-argument’)

class method g called

cls: <class ‘main.MyClass’>

arg: my-argument

c.h(‘my-argument’)

static method h called

arg: my-argument

当我们调用c.g或c.h,但实例成员没有这样的名称时,Python会搜索类和静态成员。

继承


继承是面向对象编程的另一个重要特性。在这个概念中,类(称为子类或派生类)会继承其他类(称为超类或基类)的数据和函数成员。

在Python中,所有类都会默认继承Python自带的类对象。但是,我们可以根据需要定义合适的类继承层次结构。

例如,我们可以创建一个名为MyOtherClass的新类,该类继承了MyClass:

class MyOtherClass(MyClass):

… def init(self, u, v, w, x, y, z):

… super().init(x, y, z)

… self.__u, self.__v, self.__w = u, v, w

… def f_(self, arg):

… print(‘instance method f_ called’)

… print(f’instance: {self}')

… print(f’instance attributes:\n{vars(self)}')

… print(f’class: {type(self)}')

… print(f’arg: {arg}')

d = MyOtherClass(1, 2, 4, 8, 16, 32)

如上,MyOtherClass拥有MyClass的成员:.x、._y、.__z以及.f()。你可以通过语句super().init(x, y, z)初始化基类的数据成员x、._y和.__z,该语句会调用基类的.init()方法。

除此之外,MyOtherClass还有自己的成员:.__u、.__v、._w和.f()。

下面,我们通过vars()获取数据成员:

vars(d)

{‘x’: 8,

‘_y’: 16,

‘_MyClass__z’: 32,

‘_MyOtherClass__u’: 1,

‘_MyOtherClass__v’: 2,

‘_MyOtherClass__w’: 4}

我们可以调用基类和派生类中的所有方法:

d.f(‘some-argument’)

instance method f called

instance: <main.MyOtherClass object at 0x7f32ef3e7048>

instance attributes:

{‘x’: 8,

‘_y’: 16,

‘_MyClass__z’: 32,

‘_MyOtherClass__u’: 1,

‘_MyOtherClass__v’: 2,

‘_MyOtherClass__w’: 4}

class: <class ‘main.MyOtherClass’>

arg: some-argument

d.f_(‘some-argument’)

instance method f_ called

instance: <main.MyOtherClass object at 0x7f32ef3e7048>

instance attributes:

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)

on开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-cA0gbwNe-1713778484908)]

[外链图片转存中…(img-s28lerxa-1713778484909)]

[外链图片转存中…(img-CtutpnWo-1713778484910)]

[外链图片转存中…(img-WAhNySd3-1713778484911)]

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注:Python)

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值