Python面向对象编程中的类和对象学习教程
Python中一切都是对象。类提供了创建新类型对象的机制。这篇教程中,我们不谈类和面向对象的基本知识,而专注在更好地理解Python面向对象编程上。假设我们使用新风格的python类,它们继承自object父类。
定义类
class 语句可以定义一系列的属性、变量、方法,他们被该类的实例对象所共享。下面给出一个简单类定义:
类定义引入了以下新对象:
类对象
实例对象
方法对象
类对象
程序执行过程中遇到类定义时,就会创建新的命名空间,命名空间包含所有类变量和方法定义的名称绑定。注意该命名空间并没有创建类方法可以使用的新局部作用域,因此在方法中访问变量需要全限定名称。上一节的Account类演示了该特性;尝试访问num_of_accounts变量的方法需要使用全限定名称Account.num_of_accounts,否则,如果没有在__init__方法中使用全限定名称,会引发如下错误:
类定义执行的最后,会创建一个类对象。在进入类定义之前有效的那个作用域现在被恢复了,同时类对象被绑定到类定义头的类名上。
先偏离下话题,你可能会问如果创建的类是对象,那么类对象的类是什么呢?。与一切都是对象的python哲学一致,类对象确实有个类,即python新风格类中的type类。
让你更迷惑一点,Account类型的类型是type。type类是个元类,用于创建其他类,我们稍后教程中再介绍。
类对象支持属性引用和实例化。属性通过标准的点语法引用,即对象后跟句点,然后是属性名:obj.name。有效的属性名是类对象创建后类命名空间中出现的所有变量和方法名。例如:
类实例化使用函数表示法。实例化会像普通函数一样无参数调用类对象,如下文中的Account类:
类对象实例化之后,会返回实例对象,如果类中定义了__init__方法,就会调用,实例对象作为第一个参数传递过去。这个方法会进行用户自定义的初始化过程,比如实例变量的初始化。Account类为例,账户name和balance会被设置,实例对象的数目增加1。
实例对象
如果类对象是饼干切割刀,饼干就是实例化类对象的结果。实例对象上的全部有效操作为对属性、数据和方法对象的引用。
方法对象
方法对象和函数对象类似。如果x是Account类的实例,x.deposit就是方法对象的例子。方法定义中有个附加参数,self。self指向类实例。为什么我们需要把实例作为参数传递给方法?方法调用能最好地说明:
实例方法调用时发生了什么?你应该注意到x.inquiry()调用时没有参数,虽然方法定义包含self参数。那么这个参数到底发生了什么?
特殊之处在于方法所作用的对象被作为函数的第一个参数传递过去。在我们的例子中,对x.inquiry()的调用等价于Account.f(x)。一般,调用n参数的方法等同于将方法的作用对象插入到第一个参数位置。
python教程上讲:
当引用的实例属性不是数据属性时,就会搜索类。如果名称表示一个合法的函数对象,实例对象和函数对象将会被打包到一个抽象对象,即方法对象中。包含参数列表的方法对象被调用时,将会根据实例对象和参数列表创建一个新的参数列表,然后函数对象将会使用新的参数列表被调用。
这适用于所有的实例方法对象,包括__init__方法。self参数其实不是一个关键字,任何有效的参数名都可以使用,如下Account类定义所示:
静态和类方法
类中定义的方法默认由实例调用。但是,我们也可以通过对应的@staticmethod和@classmethod装饰器来定义静态或类方法。
静态方法
静态方式是类命名空间中的普通函数。引用类的静态方法返回的是函数类型,而不是非绑定方法类型:
使用@staticmethod装饰器来定义静态方法,这些方法不需要self参数。静态方法可以更好地组织与类相关的代码,也可以在子类中被重写。
类方法
类方法由类自身来调用,而不是实例。类方法使用@classmethod装饰器定义,作为第一个参数被传递给方法的是类而不是实例。
类方法一个常见的用法是作为对象创建的工厂。假如Account类的数据格式有很多种,比如元组、json字符串等。由于Python类只能定义一个__init__方法,所以类方法在这些情形中就很方便。以上文Account类为例,我们想根据一个json字符串对象来初始化一个账户,我们定义一个类工厂方法from_json,它读取json字符串对象,解析参数,根据参数创建账户对象。另一个类实例的例子是dict.fromkeys 方法,它从一组键和值序列中创建dict对象。
Python特殊方法
有时我们希望自定义类。这需要改变类对象创建和初始化的方法,或者对某些操作提供多态行为。多态行为允许定制在类定义中某些如+等python操作的自身实现。Python的特殊方法可以做到这些。这些方法一般都是__*__形式,其中*表示方法名。如__init__和__new__来自定义对象创建和初始化,__getitem__、__get__、__add__、__sub__来模拟python内建类型,还有__getattribute__、__getattr__等来定制属性访问。只有为数不多的特殊方法,我们讨论一些重要的特殊方法来做个简单理解,python文档有全部方法的列表。
进行对象创建的特殊方法
新的类实例通过两阶段过程创建,__new__方法创建新实例,__init__初始化该实例。用户已经很熟悉__init__方法的定义;但用户很少定义__new__方法,但是如果想自定义类实例的创建,也是可以的。
属性访问的特殊方法
我们可以通过实现以下方法来定制类实例的属性访问。
__getattr__(self, name)__:这个方法只有当name既不是实例属性也不能在对象的类继承链中找到时才会被调用。这个方法应当返回属性值或者引发AttributeError异常。例如,如果x是Account类的实例,尝试访问不存在的属性将会调用这个方法。
注意如果 __getattr__引用不存在的实例属性,可能会发生死循环,因为__getattr__方法不断被调用。
2.__setattr__(self, name, value)__:这个方法当属性赋值发生时调用。__setattr__将会把值插入到实例属性字典中,而不是使用self.name=value,因为它会导致递归调用的死循环。
3.__delattr__(self, name)__:del obj发生时调用。
4.__getattribute__(self, name)__:这个方法会被一直调用以实现类实例的属性访问。
类型模拟的特殊方法
对某些类型,Python定义了某些特定语法;比如,列表和元组的元素可以通过索引表示法来访问,数值可以通过+操作符来进行加法等等。我们可以创建自己的使用这些特殊语法的类,python解释器遇到这些特殊语法时就会调用我们实现的方法。我们在下面用一个简单的例子来演示这个特性,它模拟python列表的基本用法。
上面,CustomList是个真实列表的简单包装器。我们为了演示实现了一些自定义方法:
__len__(self):对CustomList实例调用len()函数时被调用。
2.__getitem__(self, value):提供CustomList类实例的方括号索引用法支持:
>>> myList = CustomList()
>>> myList.append(1)
>>> myList.append(2)
>>> myList.append(3)
>>> myList.append(4)
>>> myList[3]
4
3.__setitem__(self, key, value):当对CustomList类实例上self[key]赋值时调用。
>>> myList = CustomList()
>>> myList.append(1)
>>> myList.append(2)
>>> myList.append(3)
>>> myList.append(4)
>>> myList[3] = 100
4
>>> myList[3]
100
4.__contains__(self, key):成员检测时调用。如果包含该项就返回true,否则false。
>>> myList = CustomList()
>>> myList.append(1)
>>> myList.append(2)
>>> myList.append(3)
>>> myList.append(4)
>>> 4 in myList
True
5.__repr__(self):当用print打印self时调用,将会打印self的对象表示。
>>> myList = CustomList()
>>> myList.append(1)
>>> myList.append(2)
>>> myList.append(3)
>>> myList.append(4)
>>> print myList
[1, 2, 3, 4]
6.__add__(self, otherList):使用+操作符来计算两个CustomList实例相加时调用。
>>> myList = CustomList()
>>> otherList = CustomList()
>>> otherList.append(100)
>>> myList.append(1)
>>> myList.append(2)
>>> myList.append(3)
>>> myList.append(4)
>>> myList + otherList + otherList
[1, 2, 3, 4, 100, 100]
上面的例子演示了如何通过定义某些特殊类方法来定制类行为。可以在Python文档中查看这些自定义方法的完整列表。
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
Excel是数据分析的重要工具,强大的内置功能使其成为许多分析师的首选。在日常工作中,启用Excel的数据分析工具库能够显著提升数 ...
2024-12-23在当今信息爆炸的时代,数据分析师如同一位现代社会的侦探,肩负着从海量数据中提炼出有价值信息的重任。在这个过程中,掌握一系 ...
2024-12-23在现代的职场中,制作吸引人的PPT已经成为展示信息的重要手段,而其中数据对比的有效呈现尤为关键。为了让数据在幻灯片上不仅准 ...
2024-12-23在信息泛滥的现代社会,数据分析师已成为企业决策过程中不可或缺的角色。他们的任务是从海量数据中提取有价值的洞察,帮助组织制 ...
2024-12-23在数据驱动时代,数据分析已成为各行各业的必需技能。无论是提升个人能力还是推动职业发展,选择一条适合自己的学习路线至关重要 ...
2024-12-23在准备数据分析师面试时,掌握高频考题及其解答是应对面试的关键。为了帮助大家轻松上岸,以下是10个高频考题及其详细解析,外加 ...
2024-12-20互联网数据分析师是一个热门且综合性的职业,他们通过数据挖掘和分析,为企业的业务决策和运营优化提供强有力的支持。尤其在如今 ...
2024-12-20在现代商业环境中,数据分析师是不可或缺的角色。他们的工作不仅仅是对数据进行深入分析,更是协助企业从复杂的数据信息中提炼出 ...
2024-12-20随着大数据时代的到来,数据驱动的决策方式开始受到越来越多企业的青睐。近年来,数据分析在人力资源管理中正在扮演着至关重要的 ...
2024-12-20在数据分析的世界里,表面上的技术操作只是“入门票”,而真正的高手则需要打破一些“看不见的墙”。这些“隐形天花板”限制了数 ...
2024-12-19在数据分析领域,尽管行业前景广阔、岗位需求旺盛,但实际的工作难度却远超很多人的想象。很多新手初入数据分析岗位时,常常被各 ...
2024-12-19入门数据分析,许多人都会感到“难”,但这“难”究竟难在哪儿?对于新手而言,往往不是技术不行,而是思维方式、业务理解和实践 ...
2024-12-19在如今的行业动荡背景下,数据分析师的职业前景虽然面临一些挑战,但也充满了许多新的机会。随着技术的不断发展和多领域需求的提 ...
2024-12-19在信息爆炸的时代,数据分析师如同探险家,在浩瀚的数据海洋中寻觅有价值的宝藏。这不仅需要技术上的过硬实力,还需要一种艺术家 ...
2024-12-19在当今信息化社会,大数据已成为各行各业不可或缺的宝贵资源。大数据专业应运而生,旨在培养具备扎实理论基础和实践能力,能够应 ...
2024-12-19阿里P8、P9失业都找不到工作?是我们孤陋寡闻还是世界真的已经“癫”成这样了? 案例一:本硕都是 985,所学的专业也是当红专业 ...
2024-12-19CDA持证人Louis CDA持证人基本情况 我大学是在一个二线城市的一所普通二本院校读的,专业是旅游管理,非计算机非统计学。毕业之 ...
2024-12-18最近,知乎上有个很火的话题:“一个人为何会陷入社会底层”? 有人说,这个世界上只有一个分水岭,就是“羊水”;还有人说,一 ...
2024-12-18在这个数据驱动的时代,数据分析师的技能需求快速增长。掌握适当的编程语言不仅能增强分析能力,还能帮助分析师从海量数据中提取 ...
2024-12-17在当今信息爆炸的时代,数据分析已经成为许多行业中不可或缺的一部分。想要在这个领域脱颖而出,除了热情和毅力外,你还需要掌握 ...
2024-12-17