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:
0
8:         """ This is a class of workers working in the company."""
0
9:
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 on %s' % (self.name, w, n, self.language, self.OS)
38:
39:     ##------------------------------------------------------------------------------------------------
40:     henley = ITWorkers('PHP''Henley''web creator''henley@livegate.com'32700)
41:     thomas = ITWorkers('Python''Thomas''server administrator''thomas@livegate.com'37900)
42:     gates  = ITWorkers('C''Gates''programmer''gates@livegate.com'421200)
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 on Mac
Thomas checks the trafic 
for 7 hours, using Python on Linux
Gates writes programs 
for 10 hours, using C on WinNT

 

 

4.假如Python没有class system?

这里我们思考一下,假如Python没有class system,我们应该如何处理这种情况呢。当然,可以不使用OOP来写程序,但在这里,我们想创建属于自己的class system。

实际上,使用把函数当成数据一样来对待的编程语言(广义上指函数式语言)来创建OOP语言是非常简单的。可以使用hash表(Python里称字典)来表示各个对象的名字空间,对象的层次构造也可以根据hash表的层次结构来表示。由于Python也是把函数当成数据来对待,所以很容易实现OOP。

我们尝试用自己的class system来重新把workers.py写一遍。参考重新编写的代码,那您应该明白方法的第一个参数为什么是self了。

[code 2] (workers2.py) 

 

01:     #! /usr/bin/env python
02:
03:     """
04:     This code demostrates how easy to imprement an object orientated system on a functional programming language.
05:     It only requires a nested hash table.
06:     
"""
07:
0
8:
0
9:     def Cls(cls=None, **key):
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 on %s' %
(geta(self, 
'name'), w, n, geta(self, 'language'), geta(self, 'OS'))
49:
50:         workers = Cls() # dummy class
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='henley@livegate.com', age=32, salary=700)
55:         thomas = new(it_workers, language='Python', name='Thomas',
56:                      position='server administrator', email='thomas@livegate.com', age=37, salary=900)
57:         gates  = new(it_workers, language='C', name='Gates',
58:                      position='programmer', email='gates@livegate.com', 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)

相关文章:

  • 2021-12-18
  • 2021-12-24
  • 2021-08-22
  • 2021-06-19
  • 2021-05-02
  • 2021-09-24
  • 2021-05-29
  • 2021-12-09
猜你喜欢
  • 2021-12-31
  • 2021-08-28
  • 2021-09-16
  • 2021-05-30
  • 2022-02-12
  • 2021-11-23
  • 2021-08-11
相关资源
相似解决方案