python,Python Class System

如果您有疑问或建议,请进入技术讨论区交流 >>>
     1.序言
  
  本文旨在说明:在Python里自定义class时,方法的第一个参数必须是该class的instance自身的引用(一般用self命名)。
  
  在其他语言里,定义方法的时候,第一个参数不必是类实例的引用,一般约定俗成用this关键字来表示当前实例的引用,可是Python自成一派。由于网络上绝大部分文章都说成这是硬性规定,因此笔者觉得很有必要去研究一下Python里的class System是如何构筑起来的,并在此基础上说明self一词的作用。
  
  2.面向对象编程
  
  对象是数据和对数据的相关操作的封装。属于对象的数据与操作也可以称之为对象的属性(attributes)。对象具有层次构造,最下层的称之为instance,在其之上的称为class。class也具有层次构造,下层class会继承上层class的属性。有必要的时候可以再定义上层的属性。在Python里,一个class可以继承多个class(多重继承)。
  
  更多内容详见Wikipedia (日本語) 和 Wikipedia (英語)。
  
  3.Python里class的一般写法
  
  首先,我们使用Python的class system来写一段程序。
  
  IT公司“LiveGate”雇佣了大量的IT技术人员,并用Python写了一个管理技术人员信息的程序。理应用数据库来储存这些信息,但这里出于演示方便就不使用了。接着我们看一下表示IT技术人员的class的代码:
  
  [code1](workers.py)
  
  01: #! /usr/bin/env python
  02:
  03: """
  04: Workers in a IT company named LiveGate
  05: """
  06:
  07: class Workers:
  08: """ This is a class of workers working in the company."""
  09:
  10: def __init__(self, name, position, email, age, salary):
  11: self.name = name
  12: self.position = position
  13: self.email = email
  14: self.age = age
  15: self.salary = salary
  16:
  17:
  18: class ITWorkers(Workers):
  19: """ This is a class of IT engineers. """
  20:
  21: OS = 'WinNT'
  22:
  23: def __init__(self, language, *av):
  24: Workers.__init__(self, *av)
  25: self.language=language
  26:
  27: def work(self, n):
  28: """ IT engineers should work."""
  29:
  30: if self.position == 'web creator':
  31: w = 'makes web site'
  32: elif self.position == 'server administrator':
  33: w = 'checks the trafic'
  34: elif self.position == 'programmer':
  35: w = 'writes programs'
  36:
  37: print '%s %s for %d, hours using %s _disibledevent=>PHP', 'Henley', 'web creator', '[email protected]', 32, 700)
  41: thomas = ITWorkers('Python', 'Thomas', 'server administrator', '[email protected]', 37, 900)
  42: gates = ITWorkers('C', 'Gates', 'programmer', '[email protected]', 42, 1200)
  43:
  44: henley.OS = 'Mac'
  45: thomas.OS = 'Linux'
  46:
  47: if __name__ == '__main__':
  48:
  49: henley.work(8)
  50: thomas.work(7)
  51: gates.work(10)
  
  
  首先定义表示劳动者的class Workers(7--15行),接着定义它的子类ITWorkers(18--37行)。18行的ITWorkers(Workers)表示ITWorkers从Workers继承而来。ITWorkers从父类Workers继承其属性。Workers类的实例在初始化的时候,其实例变量:姓名,职业类别,e-mail地址,年龄,薪金将被存储起来。除此之外,ITWorkers会把使用语言(language)作为实例变量保存下来。出来传入language参数外,其他的参数由*av(元组)传递(当调用Workers.__init__时将其展开)。BTW,__init__是在实例构造完毕之后马上调用的专用方法(special method)(该专用方法是可选的,接近于其他OOP语言里的构造函数)。
  
  接着,必须让IT技术人员按其薪金的多少来工作,因此定义方法work(25--33行)。work的第二个参数n表示工作时间。在这里,根据职业类型而分配其工作内容和工作时间,还有其使用的编程语言和操作系统类型。ITWorkers类里定义了类变量OS,其默认值为'WinNT'(19行)。也就是说,LiveGate公司里一般使用的操作系统是WindowNT。接着,我们定义3位IT技术人员,Henley, Thomas, Gates。Henley是Web开发者,作为一名艺术家,他使用Mac(44行)。Thomas是系统管理人员,工作上的关系,他使用Linux(44行)。编程人员Gates只要能用上编辑器(Editor)就可以了,对操作系统没什么特别要求,使用的是默认的'WinNT'。Henley, Thomas, Gates他们今天的工作时长为8, 7, 10个小时(43--45行)。
  
  这里需要注意的是,为Henley和Thomas设定了不同的操作系统,则往他们的名字空间(namespace)里添加了OS这一项(entry)。由于Gates的名字空间里没有该条目,则往ITWorkers名字空间里搜寻。Henley和Thomas都能在自己的名字空间里找到OS,所以不用向上搜寻。同样的,因为work这一项不存在于每个IT技术人员的名字空间里,所以要往ITWorkers的名字空间里搜寻。
  
  执行workers.py后,输出如下所示:
  
  D:\doc\05-07\py_test>python workers.py
  Henley makes web site for 8 hours, using PHP _disibledevent=>  10: """ making a new class"""
  11: key['class'] = cls
  12: return key
  13:
  14: def new(cls, **key):
  15: """ making an instance """
  16: key['class'] = cls
  17: return key
  18:
  19:
  20: def geta(obj, attr):
  21: """ getting the attribute of object """
  22: if attr in obj:
  23: return obj[attr]
  24: elif(obj['class']):
  25: return geta(obj['class'], attr)
  26: else:
  27: return None
  28:
  29: def tell(obj, method, *av):
  30: """ tell object do something"""
  31: fun=geta(obj, method)
  32: if callable(fun):
  33: return fun(obj, *av)
  34:
  35: if __name__=='__main__':
  36:
  37: def it_work(self, n):
  38: """This funciton demonstrates how IT engineers work.
  39: Notice that arguments of thie function is identical to the method 'work' in workers.py"""
  40:
  41: if geta(self, 'position') == 'web creator':
  42: w = 'makes web site'
  43: elif geta(self, 'position') == 'server administrator':
  44: w = 'checks the trafic'
  45: elif geta(self, 'position') == 'programmer':
  46: w = 'writes programs'
  47:
  48: print '%s %s for %d, hours using %s _disibledevent=>  51: it_workers = Cls(workers, OS='winNT', work=it_work) # class of IT workers
  52:
  53: henley = new(it_workers, language='PHP', name='henley',
  54: position='web creator', email='[email protected]', age=32, salary=700)
  55: thomas = new(it_workers, language='Python', name='Thomas',
  56: position='server administrator', email='[email protected]', age=37, salary=900)
  57: gates = new(it_workers, language='C', name='Gates',
  58: position='programmer', email='[email protected]', age=42, salary=1200)
  59: henley['OS'] = 'Mac'
  60: thomas['OS'] = 'Linux'
  61:
  62: tell(henley, 'work', 8)
  63: tell(thomas, 'work', 7)
  64: tell(gates, 'work', 10)
  
  
  为了简化代码,workers2.py里并没有实现多重继承。
  
  先看一下创建class的函数Cls和创建instance的函数new。实际上,两者是等同的,它们只是返回添加了表示父类'class'的hash表。
  
  接下来看一下geta函数。这是一个搜索对象属性的函数。如果对象的hash表里没有目标属性,那么将递归地往父类的hash表里搜寻。这样一来,就能实现继承和重载(override)了。没有目标属性就向上一层搜寻,这样实现了属性的继承。假如下层的对象有定义该属性,则无视上层同名属性,这样实现了属性的再定义(override)。
  
  函数tell告对象需要执行的方法。首先使用geta来搜索方法。然后如果找到的方法是函数(callable)的话,执行之,并返回结果。
  
  这样便完成了定义class system的函数Cls, new, geta, tell。请注意它们都是简单定义的函数。
  
  使用刚才创建好的class system,把workers.py重新写一次,如37行后面的代码所示。
  
  先定义表示IT技术人员工作的函数it_work。请注意它的第一个参数是self。在函数it_work里使用geta来获取IT技术人员的属性。
  
  接着,创建类it_workers时,把指向函数it_work的pointer赋值给其'work’属性。也就是说,hash表it_workers的'work'键(key)的值是指向it_work的pointer。只要能把函数当成数据来对待,就能够实现往hash表里填充函数。(译注:hash表里存储的是指向函数的引用)
  
  跟workers.py一样,分别定义了3位IT技术人员。由于模拟专用发法__init__并不简单,所以这里在创建实例的时候,把IT技术人员的相关属性全都当成参数传递。接着使用函数tell使他们工作起来。输出的结果跟workers.py一样:
  
  D:\doc\05-07\py_test>python workers2.py
  Henley makes web site for 8 hours, using PHP _disibledevent=>C++, Java, Ruby等相异。
  
  Python把过程的定义合并成函数的定义(没有将函数的定义与方法的定义区分开来),但在定义方法时,第一个参数必须是实例的引用。这是约定俗成的。
  
  函数式语言要比面向对象语言更加抽象。Python深受函数式语言Haskell的影响。实际上,像[code 2]所示的那样,函数式语言可以简单地实现面向对象编程。
  
  本文出处:http://www.shido.info/py/python7.HTML
  
  后记:
  
  由于刚接触Python,一时对它的self概念有点混乱,随手google了一下。见此好文,试译一下。翻译不当或用辞不当之处请各位看官指正
  
  作者:Nicholas.Yuen
  出处:http://randomforce.cnblogs.com/
  
  本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。  
Tags:  python平台 python

延伸阅读

最新评论

发表评论