你的位置:韩国女主播朴妮唛全集 > 雨宫琴音贴吧 > 色吧中文网 Python Class System - Nicholas Yuen - 博客园
色吧中文网 Python Class System - Nicholas Yuen - 博客园
发布日期:2024-12-13 03:53    点击次数:127

色吧中文网 Python Class System - Nicholas Yuen - 博客园

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 on %s' % (self.name, w, n, self.language, self.OS)
38:
39:     ##------------------------------------------------------------------------------------------------
40:     henley = ITWorkers('PHP', 'Henley', 'web creator', 'henley@livegate.com', 32, 700)
41:     thomas = ITWorkers('Python', 'Thomas', 'server administrator', 'thomas@livegate.com', 37, 900)
42:     gates  = ITWorkers('C', 'Gates', 'programmer', 'gates@livegate.com', 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行)。

小77论坛最新地址

这里需要耀眼的是,为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:
08:
09:     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)

 

为了简化代码,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 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],不错看出他们相似的场所:

这并不是偶然,Python里的class从旨趣上来说是这么结束的(请参考:Python reference manual 3.Data model)。实质上,Python一经为咱们准备了跟函数geta一样功能的getattr函数。况且在独特变量__dict__里界说了用于界说对象名字空间的hash表。咱们不错试试在敕令行里输入如下代码。粗体字是复返效果。

D:\doc\05-07\py_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': 'gates@livegate.com'} [2]>>> henley.__dict__ {'salary': 700, 'name': 'Henley', 'language': 'PHP', 'age': 32, 'position': 'web  creator', 'OS': 'Mac', 'email': 'henley@livegate.com'} [3]>>> ITWorkers.__dict__ {'__module__': 'workers', 'work': <function work at 0x00A34630>, 'OS': 'WinNT', '__doc__': ' This is a class 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.__class__.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)一样。由于每个实例有一个内置属性,__class__,它指向该实例所属的类,是以咱们不错像[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函数的语法糖(構文糖衣)。

从上头不错看出,在函数式谈话里引入class system时,算作步履而界说的函数,很当然地,需要指向实例的参数。通过def重要字,在类内部界说经由与界说平庸的函数一样,仅仅其作用域被终局在class内部。是以界说步履的第一个参数必须是self,不然不成援用实例里的变量。

5.结语

Python基本上是函数式谈话(广义的),面向对象是其使用hash表后的附属物良友。这少量与蓝本算作面向对象编程谈话而筹谋的C++, Java, Ruby等相异。

Python把经由的界联络并成函数的界说(莫得将函数的界说与步履的界说辩别开来),但在界说步履时,第一个参数必须是实例的援用。这是沿袭成习的。

函数式谈话要比面向对象谈话愈加玄虚。Python深受函数式谈话Haskell的影响。实质上,像[code 2]所示的那样,函数式谈话不错纯粹地结束面向对象编程。

本文出处:

跋文:

由于刚战役Python,一时对它的self见识有点浩大色吧中文网,唾手google了一下。见此好文,试译一下。翻译不妥或用辞不妥之处请列位看官指正