python系统命令:Python的class系统来源: 发布时间:星期四, 2009年1月8日 浏览:26次 评论:0
1.序言 本文旨在介绍说明:在Python里自定义时思路方法第个参数必须是该instance自身引用(般用self命名)
在其他语言里定义思路方法时候第个参数不必是类例子引用般约定俗成用this关键字来表示当前例子引用可是Python自成派由 于网络上绝大部分文章都说成这是硬性规定因此笔者觉得很有必要去研究下Python里 是如何构筑起来并在此基础上介绍说明self词作用 2.面向对象编程 对象是数据和对数据相关操作封装属于对象数据和操作也可以称的为对象属性(attributes)对象具有层次构造最下层称的为 instance在其的上称为也具有层次构造下层会继承上层属性有必要时候可以再定义上层属 性在Python里个可以继承多个(多重继承) 更多内容详见Wikipedia (日本語) 和 Wikipedia (英語) 3.Python里般写法 首先我们使用Python system来写段 IT公司“LiveGate”雇佣了大量IT技术人员并用Python写了个管理技术人员信息理应用数据库来储存这些信息但这里出于演示方便就不使用了接着我们看下表示IT技术人员代码: [code1](workers.py) 01: #! /usr/bin/env python 为了简化代码workers2.py里并没有实现多重继承先看下创建Cls和创建instance实际上两者是等同它们只是返回添加了表示父类''hash表 接下来看下geta这是个搜索对象属性如果对象hash表里没有目标属性那么将递归地往父类hash表里搜寻这样来 就能实现继承和重载(override)了没有目标属性就向上层搜寻这样实现了属性继承假如下层对象有定义该属性则无视上层同名属性这样 实现了属性再定义(override) tell告对象需要执行思路方法首先使用geta来搜索思路方法然后如果找到思路方法是(callable)话执行的并返回结果 这样便完成了定义 systemCls, , geta, tell请注意它们都是简单定义 使用刚才创建好 system把workers.py重新写次如37行后面代码所示 先定义表示IT技术人员工作it_work请注意它第个参数是self在it_work里使用geta来获取IT技术人员属性 接着创建类it_workers时把指向it_workpoer赋值给其'work’属性也就是说hash表 it_workers'work'键(key)值是指向it_workpoer只要能把当成数据来对待就能够实现往hash表里填充 (译注:hash表里存储是指向引用) 跟workers.py样分别定义了3位IT技术人员由于模拟专用发法__init__并不简单所以这里在创建例子时候把IT技术人员相关属性全都当成参数传递接着使用tell使他们工作起来输出结果跟workers.py样: D:doc5-07py_test>python workers2.py Henley makes web site for 8 hours, using PHP on Mac Thomas checks the trafic for 7 hours, using Python on Linux Gates writes programs for 10 hours, using C on winNT 对比[code 1]和[code 2]可以看出他们相似地方: [code 1] [code 2] obj.attribute geta(obj, 'attribute') obj.method(*av) tell(obj, 'method', *av) def work(self, n) def it_work(self, n) 这并不是偶然Python里从原理上来说是这样实现(请参考:Python reference manual 3.Data model)实际上Python已经为我们准备了跟geta样功能getattr而且在特殊变量__dict__里定义了用于定义对象名字空间hash表我们可以试试在命令行里输入如下代码粗体字是返回结果 D:doc5-07py_test>python Python 2.4.1 (#65, Mar 30 2005, 09:13:57) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. [x]>>> import sys [x]>>> from workers import * [1]>>> gates.__dict__ {'salary': 1200, 'name': 'Gates', 'language': 'C', 'age': 42, 'position': 'programmer', 'email': '[email protected]'} [2]>>> henley.__dict__ {'salary': 700, 'name': 'Henley', 'language': 'PHP', 'age': 32, 'position': 'web creator', 'OS': 'Mac', 'email': '[email protected]'} [3]>>> ITWorkers.__dict__ {'__module__': 'workers', 'work': <function work at 0x00A34630>, 'OS': 'WinNT', '__doc__': ' This is a of IT engineers. ', '__init__': <function __init__ at 0x00A345F0>} [4]>>> ITWorkers.work(gates, 10) Gates writes programs for 10, hours using C on WinNT [5]>>> gates.____.work(gates, 10) Gates writes programs for 10, hours using C on WinNT [6]>>> getattr(henley, 'OS') 'Mac' [7]>>> getattr(henley, 'work') <bound method ITWorkers.work of <workers.ITWorkers instance at 0x00A33760>> [8]>>> getattr(henley, 'work')(8) henley makes web site for 8 hours, using PHP on Mac 导入sys和workers模块然后试试敲进上面8行命令Gates名字空间里([1])有各类项目(entry)但是没有'OS'这 项Henley名字空间里([2])有定义'OS'ITWorkers名字空间里([3])除了预置__module__, __doc__还有我们定义'OS'work__init__ 特别思路方法(<function work at 0x00A34630>)作为被保存在内存里正如前面提及样Henley使用自身定义'OS'而Gates则向上搜寻使用类 ITWorkers里'OS'('OS'不存在Gates这个名字空间里) 在类ITWorkers里定义了work我们可以试着像[4]那样直接它其输出跟gates.work(10)样由于每个例子有个内置属性____它指向该例子所属类所以我们可以像[5]那样思路方法且得到相同结果 最后我们试试getattr像[6]那样getattr(henley, 'OS')得到结果跟henley.OS样我们把它应用到思路方法上看看([7])返回如下结果: <bound method ITWorkers.work of <workers.ITWorkers instance at 0x00A33760>> <workers.ITWorkers instance at 0x00A33760>这是 Henley在内存中地址这个不用'function'而用'bound method'表示其实'bound method'可以像[8]那样这就介绍说明了为什么从外部类思路方法时候第个参数不必是例子自身引用不过真正理由应该是那样做法不够 酷:p'bound method'可以看做是[code 2]里tell语法糖(構文糖衣) 从上面可以看出在式语言里引入 system时作为思路方法而定义很自然地需要指向例子参数通过def关键字在类里面定义过程和定义普通样只是其作用域被限定在 里面所以定义思路方法第个参数必须是self否则不能引用例子里变量 5.结语 Python基本上是式语言(广义)面向对象是其使用hash表后附属物而已这点和原本作为面向对象编程语言而设计C, Java, Ruby等相异 Python把过程定义合并成定义(没有将定义和思路方法定义区分开来)但在定义思路方法时第个参数必须是例子引用这是约定俗成 式语言要比面向对象语言更加抽象Python深受式语言Haskell影响实际上像[code 2]所示那样式语言可以简单地实现面向对象编程 0
相关文章
读者评论发表评论 |
|