关于Python面向对象编程的知识点总结


Posted in Python onFebruary 14, 2017

前言

如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程。

接下来我们就来了解关于Python面向对象编程的知识点吧。

类与实例

类是对象的定义,而实例是"真正的实物",它存放了类中所定义的对象的具体信息。

类、属性和方法命名规范

类名通常由大写字母打头。这是标准惯例,可以帮助你识别类,特别是在实例化过程中(有时看起来像函数调用)。还有,数据属性(变量或常量)听起来应当是数据值的名字,方法名应当指出对应对象或值的行为。

另一种表达方式是:数据值应该使用名词作为名字,方法使用谓词(动词加对象)。数据项是操作的对象、方法应当表明程序员想要在对象进行什么操作。

在定义的类中,大致遵循这样的方针,数据值像 “name”, “phone” 和 “email”,行为如 “updatePhone”,“updateEmail”。这就是常说的 “混合记法(mixedCase)” 或 “骆驼记法(camelCase)”。Python 规范推荐使用骆驼记法的下划线方式,比如, “update_phone”,“update_email”。类也要细致命名,像 “AddrBookEntry”, “RepairShop” 等等就是很好的名字。

class AddrBookEntry(object):

 def __init__(self, name, phone, email):
 self.name = name
 self.phone = phone
 self.email = email

 def update_phone(self, phone):
 self.phone = phone

 def update_email(self. email):
 self.email = email

新式类与旧式类

新式类和经典类声明的最大不同在于,所有新式类必须继承至少一个父类。如果没有可继承的类,则可继承 object 类。object 是“所有类之母” ,它位于所有类继承结构的最上层。如果没有直接或间接的子类化一个对象,那么就定义了一个经典类。即如果没有指定一个父类,或者如果所子类化的基本类没有父类,这样就是创建了一个经典类。

在 Python3 中定义的类,默认就是新式类,而在 Python2 中要定义一个新式类则必须继承 object 或者继承一个新式类。

self 变量

类的方法与普通的函数只有一个特别的区别,即它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不必为这个参数赋值,Python 会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是 self。虽然可以给这个参数任何名称,但是强烈建议使用 self 这个名称,其他名称都是不赞成使用的。

__init__() 方法

__init__() 类似于类构造器,但实际上并不是一个构造器。Python 创建实例后,在实例化过程中,调用 __init__() 方法,当一个类被实例化时,就可以定义额外的行为,比如,设定初始值或者运行一些初步诊断代码,这主要是在实例被创建后,实例化调用返回这个实例之前,去执行某些特定的任务或设置。

绑定及非绑定方法

在 Python 中,访问类的方法可以通过实例也可以通过类来直接访问。但是 Python 严格要求,没有实例,方法是不能被调用的。这种限制即 Python 所描述的绑定概念(binding),在此,方法必须绑定(到一个实例)才能直接被调用。非绑定的方法可能可以被调用,但实例对象一定要明确给出,才能确保调用成功。然而,不管是否绑定,方法都是它所在的类的固有属性,即使它们几乎总是通过实例来调用的。在 Python 中的类方法也是一种对象。可以简单的理解就是,通过类直接访问的方法称为“未绑定的方法”,而通过实例访问的方法称为“绑定的方法”:

1. 未绑定的类方法:没有 self

通过类来引用方法返回一个未绑定方法对象。要调用它,你必须显示地提供一个实例作为第一个参数。

2. 绑定的实例方法:有 self

通过实例访问方法返回一个绑定的方法对象。Python 自动地给方法绑定一个实例,所以我们调用它时不用再传一个实例参数。

示例:

class Test:
 def func(self, message):
 print message

object1 = Test()
x = object1.func
x("绑定方法对象,实例是隐藏的")

t = Test.func
t(object1, "未绑定方法对象,需要传递一个实例")
# t("未绑定方法对象,需要传递一个实例") # 错误的调用

类属性与实例属性

类属性仅是与类相关的数据值,和实例属性不同,类属性和实例无关。这些值像静态成员那样被引用,即使在多次实例化中调用类,它们的值都保持不变。不管如何,静态成员不会因为实例而改变它们的值,除非实例中显式改变它们的值。 实例属性与类属性的比较,类似于自动变量和静态变量,但这只是笼统的类推。在你对自动变量和静态变量还不是很熟的情况下,不要深究这些。

类和实例都是名字空间。类是类属性的名字空间,实例则是实例属性的。

可采用类来访问类属性,如果实例没有同名的属性的话,也可以用实例来访问。

私有化

Python并不直接支持私有方式,而要靠程序员自己把握在外部进行特性修改的时机。

为了让方法或者特性变为私有(从外部无法访问),只要在它的名字前面加上双下划线即可。由双下划线 __ 开始的属性在运行时被“混淆”,所以直接访问是不允许的。

实际上,在 Python 带有双下划线的属性或方法并非正真意义上的私有,它们仍然可以被访问。在类的内部定义中,所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式:

>>> class TestObj(object):
... __war = "world"
... 
... def __init__(self):
...  self.__har = "hello"
...  
... def __foo(self):
...  print(self.__har + self.__war)
...  
... 
... 
>>> t = TestObj()
>>> dir(t)
['_TestObj__foo', '_TestObj__har', '_TestObj__war', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getat
tribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__
', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>> t.__war
Traceback (most recent call last):
 File "<input>", line 1, in <module>
 t.__war
AttributeError: 'TestObj' object has no attribute '__war'
>>> t.__har
Traceback (most recent call last):
 File "<input>", line 1, in <module>
 t.__har
AttributeError: 'TestObj' object has no attribute '__har'
>>> t.foo()
Traceback (most recent call last):
 File "<input>", line 1, in <module>
 t.foo()
AttributeError: 'TestObj' object has no attribute 'foo'
>>> t._TestObj__war
'world'
>>> t._TestObj__har
'hello'
>>> t._TestObj__foo()
helloworld

__slots__ 类属性

正常情况下,当我们定义了一个 class,创建了一个 class 的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。在 Python 中默认用字典来存储实例的属性。

示例:

>>> class A():
... pass
... 
>>> a = A()
>>> a.name = "huoty"
>>> a.age = 25
>>> print a.name
huoty
>>> print a.age
25
>>> a.__dict__
{'age': 25, 'name': 'huoty'}

字典位于实例的“心脏” 。 __dict__属性跟踪所有实例属性。举例来说,你有一个实例 inst,它有一个属性 foo,那使用 inst.foo 来访问它与使用 inst.__dict__['foo'] 来访问是一致的。

字典会占据大量内存,如果你有一个属性数量很少的类,但有很多实例,那么正好是这种情况。为内存上的考虑,可以使用 __slots__ 属性来替代 __dict__

__slots__ 是新式类的特性。基本上, __slots__ 是一个类变量,由一序列对象组成,由所有合法标识构成的实例属性的集合来表示。它可以是一个列表,元组或可迭代对象。也可以是标识实例能拥有的唯一的属性的简单字符串。任何试图创建一个其名不在 __slots__ 中的名字的实例属性都将导致 AttributeError 异常:

>>> class SlotedClass(object):
... __slots__ = ("foo", "bar")
... 
... 
>>> c = SlotedClass()
>>> c.foo = 42
>>> c.bar = "hello"
>>> c.goo = "don't think so"
Traceback (most recent call last):
 File "<input>", line 1, in <module>
AttributeError: 'SlotedClass' object has no attribute 'goo'

这种特性的主要目的是节约内存。其副作用是某种类型的"安全",它能防止用户随心所欲的动态增加实例属性。带 __slots__ 属性的类定义不会存在 __dict__ 了(除非你在 __slots__ 中增加 __dict__ 元素)。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Python 相关文章推荐
linux环境下安装pyramid和新建项目的步骤
Nov 27 Python
python实现简单温度转换的方法
Mar 13 Python
约瑟夫问题的Python和C++求解方法
Aug 20 Python
Python中MySQL数据迁移到MongoDB脚本的方法
Apr 28 Python
Python实现将一个大文件按段落分隔为多个小文件的简单操作方法
Apr 17 Python
python移位运算的实现
Jul 15 Python
python绘制无向图度分布曲线示例
Nov 22 Python
Scrapy框架实现的登录网站操作示例
Feb 06 Python
DataFrame.groupby()所见的各种用法详解
Jun 14 Python
Python日志器使用方法及原理解析
Sep 27 Python
使用Pytorch搭建模型的步骤
Nov 16 Python
Django+Django-Celery+Celery的整合实战
Jan 20 Python
Django日志模块logging的配置详解
Feb 14 #Python
深入理解Python对Json的解析
Feb 14 #Python
Python 2与Python 3版本和编码的对比
Feb 14 #Python
利用Python爬虫给孩子起个好名字
Feb 14 #Python
python 出现SyntaxError: non-keyword arg after keyword arg错误解决办法
Feb 14 #Python
让python 3支持mysqldb的解决方法
Feb 14 #Python
python用装饰器自动注册Tornado路由详解
Feb 14 #Python
You might like
网友原创的PHP模板类代码
2008/09/07 PHP
PHP 小心urldecode引发的SQL注入漏洞
2011/10/27 PHP
php截取后台登陆密码的代码
2012/05/05 PHP
php ctype函数中文翻译和示例
2014/03/21 PHP
WordPress网站性能优化指南
2015/11/18 PHP
PHP会话操作之cookie用法分析
2016/09/28 PHP
利用php获得flv视频长度的实例代码
2017/10/26 PHP
详解关于php的xdebug配置(编辑器vscode)
2019/01/29 PHP
laravel-admin 在列表页添加自定义按钮的例子
2019/09/30 PHP
PHP设计模式入门之迭代器模式原理与实现方法分析
2020/04/26 PHP
理解Javascript_08_函数对象
2010/10/15 Javascript
javaScript对文字按照拼音排序实现代码
2013/12/27 Javascript
解析jQuery的三种bind/One/Live事件绑定使用方法
2013/12/30 Javascript
详解JavaScript 中的 replace 方法
2016/01/01 Javascript
超详细的JS弹出窗口代码大全
2020/04/18 Javascript
浅谈AngularJS中ng-class的使用方法
2016/11/11 Javascript
Jquery Easyui表单组件Form使用详解(30)
2016/12/19 Javascript
javascript 实现文本使用省略号替代(超出固定高度的情况)
2017/02/21 Javascript
详解 vue.js用法和特性
2017/10/15 Javascript
在Bootstrap开发框架中使用dataTable直接录入表格行数据的方法
2018/10/25 Javascript
Node.js原生api搭建web服务器的方法步骤
2019/02/15 Javascript
详细讲解如何创建, 发布自己的 Vue UI 组件库
2019/05/29 Javascript
Vue学习之常用指令实例详解
2020/01/06 Javascript
Vue SSR 即时编译技术的实现
2020/05/06 Javascript
[02:41]《西雅图我们来了》2015国际邀请赛出征全记录
2015/07/23 DOTA
[01:25:33]完美世界DOTA2联赛PWL S3 INK ICE vs Magma 第二场 12.20
2020/12/23 DOTA
用python登录Dr.com思路以及代码分享
2014/06/25 Python
一个简单的python爬虫程序 爬取豆瓣热度Top100以内的电影信息
2018/04/17 Python
python3.6 如何将list存入txt后再读出list的方法
2019/07/02 Python
html5+CSS3+JS实现七夕言情功能代码
2017/08/28 HTML / CSS
Original Penguin英国官方网站:美国著名休闲时装品牌
2016/10/30 全球购物
幼儿教师个人求职信范文
2013/09/21 职场文书
大学毕业生的自我鉴定
2013/11/30 职场文书
大学生自荐信
2013/12/11 职场文书
校园公益广告语
2014/03/13 职场文书
2014年电信员工工作总结
2014/12/19 职场文书