标题: MBMOD入门介绍, 非原创,转载加工处理
性别:未知-离线 風清揚

Rank: 1
组别 百姓
级别 在野武将
功绩 0
帖子 9
编号 243689
注册 2007-12-2


发表于 2007-12-2 18:12 资料 短消息 看全部作者
MBMOD入门介绍

MBMOD代码编写指南

首先准备手头上的东西:
1 下载python                                     (一种编程语言)
2 下载官方mod代码.                           (mod的代码都是在官方代码的基础上修改而成.)
3 下载source insight并按步骤设置,ultraedit和ultracompare其实是用不到的.



几个重要的概念:


1.游戏构架  
        世界地图
    /                \
菜单      ---------     场景

注:整个游戏就是在世界地图,菜单和场景中的不断切换.(在这里把”对话”部分也看成菜单)

2.主角遇到别的party时(城镇其实也是一种party),触发菜单,选择菜单项之后,调用场景(野战场景或城镇场景)   

3.场景中包含很多元素,比如道具,物品,树木等,但其中最重要的元素是entry point,它决定了人出现在场景的具体坐标位置,比如野战场景中,主角方出现在正方形战场的一侧,敌人出现在另一侧.

entry point设置方法:在游戏最初的配置中选择”windows模式”和”edit模式”,打开游戏,进入某个场景,按ctrl+e,就可以在某些位置发现在native中已经设置好的entry point.如果添加或减少entry point,整个场景的数据将保存在Sceneobj目录下的sco文件中.(也就是场景的结构都是存在于这些sco文件中的).

以上介绍的是一些简单概念,但掌握这些概念是最重要的理解mod编程的手段.


顶部
性别:未知-离线 風清揚

Rank: 1
组别 百姓
级别 在野武将
功绩 0
帖子 9
编号 243689
注册 2007-12-2


发表于 2007-12-2 18:14 资料 短消息 看全部作者
如何阅读官方的py文件?

只有Module_*.py文件是我们需要修改的.
Header_operations.py是我们常用的操作符.
就像C语言一样,if 是判断语句的操作符,而编写mod代码的操作符就存在于header_operations中.

阅读任何一个module_*.py文件,最重要的是看文件头的注释部分,这实质说明了后面代码的一个模板.
例子:module_mission_templates.py文件开始部分的注释是:
#   Each mission-template is a tuple that contains the following fields:
#  1) Mission-template id (string): used for referencing mission-templates in other files.
#     The prefix mt_ is automatically added before each mission-template id
#
#  2) Mission-template flags (int): See header_mission-templates.py for a list of available flags
#  3) Mission-type(int): Which mission types this mission template matches.
#     For mission-types to be used with the default party-meeting system,
#     this should be 'charge' or 'charge_with_ally' otherwise must be -1.
#     
#  4) Mission description text (string).
#  5) List of spawn records (list): Each spawn record is a tuple that contains the following fields:
#    5.1) entry-no: Troops spawned from this spawn record will use this entry
#    5.2) spawn flags.
#    5.3) alter flags. which equipment will be overriden
#    5.4) ai flags.
#    5.5) Number of troops to spawn.
#    5.6) list of equipment to add to troops spawned from here (maximum 8).
#  6) List of triggers (list).
#     See module_triggers.py for infomation about triggers.
#
#  Please note that mission templates is work in progress and can be changed in the future versions.

其后的代码部分都是基于这个模板建立的.举例如下:
(
"lead_charge",mtf_battle_mode,charge,      
对照注释:”lead_charge”将成为mission_templates中的某个ID.
         mtf_battle_mode是mission_templates的flag,标志着调用的是战斗模式.
         “charge”标志战斗的类型是主角领导部队冲锋.
"You lead your men to battle.",
对照注释: 对这个mission的文字描述
    [
     (1,mtef_defenders,0,group(1)|aif_start_alarmed,8,[]),
     (0,mtef_defenders,0,group(1)|aif_start_alarmed,0,[]),
     (4,mtef_attackers,0,aif_start_alarmed,8,[]),
     (4,mtef_attackers,0,aif_start_alarmed,0,[]),
对照注释:这些是士兵如何出现在场景中的.
        首先(1,    这个1指的是出现在编号为entry point 1 的位置.即1是No.1
这个entry point.
             mtef_defenders,是指出现在entry point 1这个位置的是防守方.
             0,指要不要把防守方的某些装备脱掉,0表示不去除装备
             group(1)|aif_start_alarmed指士兵的ai,是警觉的,那么他们将跑向最近的敌人并攻击敌人.
             8指的是一次从entry point出现的人数是8个防守方的人数.(这个人数不是绝对的,人数还取决于其他条件,比如主角的统帅力.
             [ ] 里面虽然没有东西,却其实是可以添加一些装备给防守方使用.现在是没有添加任何装备     ],
     对照注释:以下的部分是触发器(triggers)理解以下代码,请看module_triggers.py的文件头注释部分,就不赘述了.
    [
      (ti_tab_pressed, 0, 0, [],
       [
           (try_begin),
             (eq, "$battle_won", 1),
             (finish_mission,0),
           (else_try),
             (call_script, "script_check_enemies_nearby"),
             (question_box,"str_do_you_want_to_retreat"),
           (else_try),
             (display_message,"str_can_not_retreat"),
           (try_end),
        ]),
      (ti_question_answered, 0, 0, [],
       [(store_trigger_param_1,":answer"),(eq,":answer",0),(finish_mission,0),]),

      (0, 0, ti_once, [], [(assign,"$battle_won",0),(assign,"$defender_reinforcement_stage",0),(assign,"$attacker_reinforcement_stage",0)]),
      (1, 0, 5, [(lt,"$defender_reinforcement_stage",2),(store_mission_timer_a,reg(1)),(ge,reg(1),10),(store_defender_count,reg(2)),(lt,reg(2),3)],
           [(add_reinforcements_to_entry,0,4),(val_add,"$defender_reinforcement_stage",1)]),
      (1, 0, 5, [(lt,"$attacker_reinforcement_stage",2),(store_mission_timer_a,reg(1)),(ge,reg(1),10),(store_attacker_count,reg(2)),(lt,reg(2),3)],
           [(add_reinforcements_to_entry,3,4),(val_add,"$attacker_reinforcement_stage",1)]),
      (1, 60, ti_once, [(store_mission_timer_a,reg(1)),
                        (ge,reg(1),10),(all_enemies_defeated,2),
                        (neg|main_hero_fallen,0),
                        (set_mission_result,1),
                        (assign, "$g_battle_result", 1),
                        (display_message,"str_msg_battle_won"),
                        (assign,"$battle_won",1)],
           [(finish_mission,1)]),
      (10, 0, 0, [], [(eq,"$battle_won",1),(display_message,"str_msg_battle_won"),]),
      (1, 4, ti_once, [(main_hero_fallen)],
          [
              (assign, "$g_battle_result", -1),
              (set_mission_result,-1),(finish_mission,1)]),
      (ti_inventory_key_pressed, 0, 0, [(display_message,"str_use_baggage_for_inventory")], []),
    ],
  ),

其他任何module_*.py文件都是这样先阅读文件头的注释部分,然后按此注释的模板去理解后面的代码的.


顶部
性别:未知-离线 風清揚

Rank: 1
组别 百姓
级别 在野武将
功绩 0
帖子 9
编号 243689
注册 2007-12-2


发表于 2007-12-2 18:17 资料 短消息 看全部作者
python 语言简单介绍:

Python
Python(发音:[ 'paiθ(ə)n; (US) 'paiθɔn ]),是一种面向对象的解释性的计算机程序设计语言,也是一种功能强大而完善的通用型语言,已经具有十多年的发展历史,成熟且稳定。Python 具有脚本语言中最丰富和强大的类库,足以支持绝大多数日常应用。

这种语言具有非常简捷而清晰的语法特点,适合完成各种高层任务,几乎可以在所有的操作系统中运行。

目前,基于这种语言的相关技术正在飞速的发展,用户数量急剧扩大,相关的资源非常多。

Python的Hello World程序

下面是一个在标准输出设备上输出Hello World的简单程序,这种程序通常作为开始学习编程语言时的第一个程序:

#!/usr/bin/env python

print "Hello, world!"

Python的历史

Python的创始人为Guido van Rossum。1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序,做为 ABC 语言的一种继承。之所以选中 Python(大蟒蛇的意思)作为程序的名字,是因为他是一个Monty Python的飞行马戏团的爱好者。

ABC是由Guido参加设计的一种教学语言。就Guido本人看来,ABC 这种语言非常优美和强大,是专门为非专业程序员设计的。但是ABC语言并没有成功,究其原因,Guido 认为是非开放造成的。Guido 决心在 Python 中避免这一错误(的确如此,Python 与其它的语言如C、C++和Java结合的非常好)。同时,他还想实现在 ABC 中闪现过但未曾实现的东西。

就这样,Python在Guido手中诞生了。实际上,第一个实现是在Mac机上。可以说,Python是从ABC发展起来,主要受到了Modula-3(另一种相当优美且强大的语言,为小型团体所设计的)的影响。并且结合了Unix shell和C的习惯。

Python在编程语言中的定位

虽然 Python 可能被粗略地分类为"脚本语言(scripting language)", 实际上一些大规模软件开发计划例如 Zope, Mnet 及 BitTorrent. Google也广泛地使用它。 Python 的支持者较喜欢称它为一种高阶动态编程语言 , 原因是"脚本语言" 泛指单用作简单编程任务如 shell scripts ,而Python不能与JavaScript等只能处理简单任务的编程语言相提并论。

Python的特色

可扩充性可说是Python作为一种编程语言的特色。新的内置模块(module)可以用C 或 C++写成。而我们也可为现成的模块加上Python的接口。Python可以使用户避免过分的语法的羁绊而将精力主要集中到所要实现的程序任务上。

Python也被称为是一门清晰的语言。因为它的作者在设计它的时候,总的指导思想是,对于一个特定的问题,只要有一种最好的方法来解决就好了。这在由Tim Peters写的python格言(称为The Zen of Python)里面表述为:

There should be one-- and preferably only one --obvious way to do it.

有意思的是,这正好和Perl语言(另一种功能类似的高级动态语言)的中心思想TMTOWTDI(There's More Than One Way To Do It)完全相反。这似乎是人们常把Perl和Python互相比较的重要原因。

Python语言是一种清晰的语言的另一个意思是,它的作者有意的设计限制性很强的语法,使得不好的编程习惯(例如if语句的下一行不向右缩进)都不能通过编译。这样有意的强制程序员养成良好的编程习惯。其中很重要的一项就是Python的缩进规则。

例如if语句:

if age<21:

    print "You cannot buy wine!\n"

    print "But you can buy chewing gum.\n"

print "this is outside if\n"

一个和其他大多数语言(如C)的区别就是,一个模块的界限,完全是由每行的首字符在这一行的位置来决定的(而C语言是用一对花括号{}来明确的定出模块的边界的,与字符的位置毫无关系)。这一点曾经引起过争议。因为自从C这类的语言诞生后,语言的语法含义与字符的排列方式分离开来,曾经被认为是一种程序语言的进步。不过不可否认的是,通过强制程序员们缩进(包括if,for和函数定义等所有需要使用模块的地方),Python确实使得程序更加清晰和美观。

另外Python在其他部分的设计上也坚持了清晰划一的风格,这使得Python称为一门易读性、易维护性好,并且被大量用户所欢迎的、用途广泛的语言。

Python的局限
虽然Python是一个非常成功的语言,但是也有必要明白它的局限性。
1. 运行效率低下
   目前为止,Python可以说是所有主流脚本语言中速度最慢的。(是这样么?待考.)这与其脚本引擎的设计思路有关。
   如果你的应用对于速度有着较高的要求,就要考虑Python是否能满足需要。不过这一点可以通
   过使用C编写关键模块,然后由Python调用的方式加以部分解决。
2. 多线程支持欠佳
   Python支持多线程,但是其运行效率也不高。
3. 独特的语法
   这也许不应该被称为局限,但是它用缩进来区分语句关系的方式还是给很多初学者带来了困惑。
   即便是很有经验的Python程序员,也可能陷入陷阱当中。最常见的情况是tab和空格的混用会导
   致错误,而这是用肉眼无法分别的。
4. 无类型
   作为一种动态语言,随时随地创建和使用变量是Python给我们带来的巨大的便利。但是它也会
   使得程序不严谨,某些错误只有在运行中才可能出现。所以,使用Python编程的时候,要对类
   型做到心里有数。这也使得Python的IDE工具无法提供便利的自动完成等功能。
关于“无类型”的说法,是完全错误的。一看就是不了解python的人写的。python是一种“强类型”“动态绑定”。

Python的前景
Python在编程领域的占有率一直处于稳步上升之中,根据最新的数据,Python排名第七。前六名分别是Java,
C,VB,C++,PHP和Perl. 作为一个很年轻的语言,Python的位置已经相当令人振奋了。随着微软将Python纳入
.Net 平台,相信Python的将来会更加强劲发展。Python 很可能会成为.Net平台快速开发的主流语言。
欲了解这方面情况,请参考Iron Python的相关信息.
著名的搜索引擎 Google 也大量使用Python。
更加令人吃惊的是,在Nokia智能手机所采用的Symbian操作系统上,Python成为继C++,Java之后的
第三个编程语言!可见Python的影响力之巨大。

Python的应用

Zope-应用服务器

Plone-内容管理系统

Django-鼓励快速开发的web framework

Twisted - Python Network Application Framework Python的网络应用程序框架

TurboGears - 另一个Web应用快速开发框架

Bit Torrent - 著名的BT下载工具

2006年的Google编程大赛已经将Python作为参赛语言之一
顶部
性别:未知-离线 風清揚

Rank: 1
组别 百姓
级别 在野武将
功绩 0
帖子 9
编号 243689
注册 2007-12-2


发表于 2007-12-2 18:26 资料 短消息 看全部作者
Python快速入门
本章是Python的快速入门,在这一章并不涉及python的特殊规则和细节,目标是通过示例使你快速了解Python语言的特点。本章简要介绍了变量,表达式,控制流,函数以及输入/输出的基本概念,在这一章不涉及Python语言的高级特性。尽管如此,有经验的程序员还是能够通过阅读本章的材料创建高级程序。我们鼓励新手通过运行示例,亲身体验一把Python。


1.1. 运行Python
Python 程序通过解释器执行。如果你的机器已经装好了python,简单的在命令行键入python即可运行python解释器。在解释器运行的时,会有一个命令提示符 >>>,在提示符后键入你的程序语句,键入的语句将会立即执行。在下边的例子中,我们在>>>提示符后边键入最常见的显示"Hello World"的命令:

Python 2.4.2 (#67, Sep 28 2005, 12:41:11) [MSC v.1310 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> print "Hello World"
Hello World
>>>


程序也可以像下面一样放置在一个文件中

# helloworld.py
print "Hello World"

Python源代码文件使用.py后缀.'#'表示注释(到行末结束)

执行文件helloworld.py

% python helloworld.py
Hello World
%
在Windows 下,只需双击一个.py文件就能执行这个python程序。windows会自动调用python解释程序,然后启动一个终端窗口(类DOS窗口)来执行它。在这种情况下,终端窗口会在程序执行完毕后立即关闭(经常是在你看到它的输出之前)。为避免这个问题,你可以使用python集成开发环境,例如IDLE或Pythonwin。另一个可行的方法是建立一个 bat文件,在文件写入这样一行语句,如 python -i helloworld.py。运行这个批处理,程序在执行完成后会自动进入python解释器。

在解释器中,也可以通过函数execfile()来运行一个保存在磁盘上的程序,如下例:

>>> execfile("helloworld.py")
Hello World
在UNIX下,你可以在程序的首行写入 #! 魔法字符串 来自动调用python解释器执行你的脚本。

#!/usr/local/bin/python
print "Hello World"
解释器会一直运行直到文件结束。如果在交互模式下,键入 EOF字符退出解释器。在UNIX下,EOF字符是Ctrl+ D;在Windows下,EOF字符是Ctrl+Z.也可以在程序中使用sys.exit()函数或者通过引发SystemExit异常来退出程序:

>>> import sys
>>> sys.exit()
或者

>>> raise SystemExit

1.2. 变量和表达式
通过Listing 1.1所示的程序示例变量和表达式的用法

Listing 1.1 复利计算器(Simple Compound-Interest Calculation)

切换行号显示
   1 principal = 1000        # Initial amount (本金)
   2 rate = 0.05             # Interest rate (利率)
   3 numyears = 5            # Number of years (期数,年)
   4 year = 1
   5 while year <= numyears:
   6         principal = principal*(1+rate)
   7         print year, principal
   8         year += 1
程序输出:

1 1050.0
2 1102.5
3 1157.625
4 1215.50625
5 1276.2815625
Python 是一种动态语言,在程序运行过程中,同一变量名可以(在程序运行的不同阶段)代表不同形式的值(整型,浮点,列表,元组...)。事实上,程序中使用的变量名只是各种数据及对象的引用。这与C语言不同,C语言中变量名代表的是用来存放结果的一个固定位置及长度的内存片段。从例子Listing 1.1中的变量principal可以看出Python语言的动态特性.最初,它被赋值为一个整数,但是稍后程序将它再次赋值:

principal = principal*(1+rate)

这个语句计算表达式的值,然后将计算结果赋给 principal 变量做为它的新值。当赋值动作发生时,principal最初绑定的值1000被丢弃。赋值结束,不但 principal 绑定的值发生了变化,它的类型也随着赋值动作发生了相应的变化。在这个例子中,由于rate是一个浮点数,所以在赋值完成后,principal也变成一个浮点数。

Python中每个语句以换行结束,当然你也可以在一行中写多个语句,这时语句之间必须使用用分号分隔,就象下面这样:

principal = 1000; rate = 0.05; numyears = 5;

(建议这样的写法仅仅用于调试语句,因为可以很方便的只删一行就删掉全部调试语句)

while 语句首先检查在它后边的循环条件,若条件表达式为真,它就执行冒号后面的语句块,然后再次测试循环条件,直至为假。冒号后面的缩近语句块为循环体。注意,Python语言使用缩进块来表示程序逻辑(其它大多数语言使用大括号等)。在Listing 1.1中while语句后的三条语句为循环体,在每次循环中均执行。Python并未指定缩进的空白(空格和制表符)数目,唯一的要求是同一层次的语句必须有相同的缩进空白。(注意,要么都是空格,要是么都制表符,千万别混用)

Listing 1.1中的程序美中不足的就是输出不是很好看,为了让它美观一点,可以用格式字符串将计算结果只保留小数点后两位:

print "%3d %0.2f" % (year, principal)

这样,程序的输出就变为:

1 1050.00
2 1102.50
3 1157.63
4 1215.51
5 1276.28
格式字符串包含普通文本及格式化字符序列(例如"%d", "%s", 和 "%f"),这些序列决定特定类型的数据(如整型,字符串,浮点数)的输出格式.'%3d'将一个整数在宽度为3个字符的栏中右对齐,'%0.2f'将一个浮点数的小数点后部分转换为2位。格式字符串的作用和C语言中的sprintf()函数基本相同。详细内容请参阅第四章--操作符及表达式。

1.3. 条件语句
if和else语句用来进行简单的测试,如:

切换行号显示
   1 # Compute the maximum (z) of a and b (得到a与b中较大的一个)
   2 if a < b:
   3         z = b
   4 else:
   5         z = a
if和else的语句块用缩近来表示,else从句在某些情况下可以省略。 如果if或else语句块只有一个语句,也可以不使用缩近。也就是说:

切换行号显示
   1 if a<b: z=a
   2 else: z=b
这样的写法也是合法的,但这不是推荐的作法。一直使用缩近可以让你方便的在语句体中添加一个语句,而且读起来更清晰。 若某个子句不需任何操作,就使用pass语句,如:

切换行号显示
   1 if a < b:
   2         pass      # Do nothing
   3 else:
   4         z = a
通过使用 or,and 和 not 关键字你可以建立任意的条件表达式:

切换行号显示
   1 if b >= a and b <= c:
   2         print "b is between a and c"
   3 if not (b < a or b > c):
   4         print "b is still between a and c"
用 elif 语句可以检验多重条件(用于代替其它语言中的switch语句):

切换行号显示
   1 if a == '+':
   2         op = PLUS
   3 elif a == '-':
   4         op = MINUS
   5 elif a == '*':
   6         op = MULTIPLY
   7 else:
   8         raise RuntimeError, "Unknown operator"

1.4. 文件输入/输出
下面的程序打开一个文件,然后一行行地读出并显示文件内容:

切换行号显示
   1 f = open("foo.txt")        # Returns a file object
   2 line = f.readline()        # Invokes readline() method on file
   3 while line:
   4         print line,        # trailing ',' omits newline character
   5         line = f.readline()
   6 f.close()
open()函数返回一个新文件对象(file object)。通过调用此对象的不同方法可以对文件进行不同的操作。readline()方法读取文件的一行(包括换行符'\n')。如果读到文件末尾,就返回一个空字符串。要将程序的输出内容由屏幕重定向到文件中,可以使用'>>'运算符,如下例:

切换行号显示
   1 f = open("out","w")     # Open file for writing
   2 while year <= numyears:
   3         principal = principal*(1+rate)
   4         print >>f,"%3d %0.2f" % (year,principal)  #将格式文本输出到文件对象 f
   5         year += 1
   6 f.close()
当然,文件对象也拥有write()方法,通过它可以向文件对象写入新的数据。例如上边例子中的print的语句也可以写成这样:

f.write("%3d   %0.2f\n" % (year,principal))  


1.5. 字符串
要创建一个字符串,你使用单引号,双引号或三引号将其引起来,如下例:

切换行号显示
   1 a = 'Hello World'
   2 b = "Python is groovy"
   3 c = """What is footnote 5?"""
一个字符串用什么引号开头,就必须用什么引号结尾。两上三引号之间的一切都作为字符串的内容,对应的单引号与双引号却只能创建单行字符串。如下例:

切换行号显示
   1 print '''Content-type: text/html
   2
   3 <h1> Hello World </h1>
   4 Click <a href="http://www.python.org">here</a>.
   5 '''
字符串是一个以0开始,整数索引的字符序列,要获得字符串 s 中的第 i+1 个字符(别忘了0是第一个),使用索引操作符 s:

切换行号显示
   1 a = "Hello World"
   2 b = a[4]                # b = 'o'
要获得一个子串,使用切片运算符 s[i:j]。 它返回字符串 s 中从索引 i (包括i)到 j (不包括 j)之间的子串。若 i 被省略,python就认为 i=0,若 j 被省略,python就认为 j=len(s)-1:

切换行号显示
   1 c = a[0:5]              # c = "Hello"
   2 d = a[6:]               # d = "World"
   3 e = a[3:8]              # e = "lo Wo"
可以用加(+)运算符来连结字符串:

g = a + " This is a test"

通过使用str()函数,repr()函数或向后的引号(`)可以将其他类型的数据转换为字符串:

切换行号显示
   1 s = "The value of x is " + str(x)
   2 s = "The value of y is " + repr(y)
   3 s = "The value of y is " + `y`
repr()函数用来取得对象的规范字符串表示,向后的引号(`)是repr()函数的快捷版。

在大多情况下str()和repr()函数会返回同一个结果,但是它们之间有很微妙的差别,后边的章节对此将有详细描述。


1.6. 列表和元组(Lists & Tuples)
就如同字符串是字符的序列,列表和元组则是任意对象的序列。象下面这样就可以创建一个列表:

names = [ "Dave", "Mark", "Ann", "Phil" ]

列表和元组都是以整数0来开始索引的序列,你可以用索引操作符来读取或者修改列表中特定元素的值:

a = names[2]             # Returns the third item of the list, "Ann"
names[0] = "Jeff"        # Changes the first item to "Jeff"

用len()函数得到列表的长度:

print len(names)        # prints 4

append()方法可以把一个新元素插入列表的末尾:

names.append("Kate")

aList.insert(index,aMember)方法可以把新元素 aMember 插入到列表 aList[index] 元素之前:

names.insert(2, "Sydney")

用切片操作符可以取出一个子列表或者对子列表重新赋值:

b = names[0:2]                      # Returns [ "Jeff", "Mark" ]
c = names[2:]                       # Returns [ "Sydney", "Ann", "Phil", "Kate" ]
names[1] = 'Jeff'                   # Replace the 2nd item in names with "Jeff"
names[0:2] = ['Dave','Mark','Jeff'] # 用右边的 list 替换 names 列表中的前两个元素
   
加(+)运算符可以连结列表:

a = [1,2,3] + [4,5]     # Result is [1,2,3,4,5]

列表元素可以是任意的 Python 对象,当然也包括列表:

a = [1,"Dave",3.14, ["Mark", 7, 9, [100,101]], 10]

子列表的元素用下面的方式调用:

a[1]            # Returns "Dave"
a[3][2]         # Returns 9
a[3][3][1]      # Returns 101
Listing 1.2中代码从一个文件中读取一系列数字,然后输出其中的最大值和最小值。 通过这个示例我们可以了解到列表的一些高级特性:

Listing 1.2 列表的高级特性

切换行号显示
   1 import sys                       # Load the sys module (导入sys模块)
   2 f = open(sys.argv[1])            # Filename on the command line (从命令行读取文件名)
   3 svalues = f.readlines()          # Read all lines into a list (读出所有行到一个列表)
   4 f.close()
   5
   6 # Convert all of the input values from strings to floats (把输入的值转换为浮点数)
   7 fvalues = [float(s) for s in svalues]
   8
   9 # Print min and max values (输出最大值和最小值)
  10 print "The minimum value is ", min(fvalues)
  11 print "The maximum value is ", max(fvalues)
程序第一行用import语句从Python library中导入sys模块。

你需要在命令行提供一个文件名给上面的程序,该文件名参数保存在sys.argv 列表中,open方法通过读取sys.argv[1]得到这个文件名参数。

readlines()方法读取文件中的所有的行到一个列表中。

表达式 [float(s) for s in svalues] 通过循环列表svalues中的所有字符串并对每个元素运行函数float()来建立一个新的列表,这种特殊的建立列表的方法叫做列表包含( list comprehension)。 在列表中所有的字符串都转换为浮点数之后,内建函数min()和max()计算出列表中的最大值及最小值。

元组(tuple)类型和列表关系很密切,通过用圆括号中将一系列逗号分割的值括起来可以得到一个元组:

切换行号显示
   1 a = (1,4,5,-9,10)
   2 b = (7,)                                 # 一个元素的元组 (注意一定要加一个额外的逗号!)
   3 person = (first_name, last_name, phone)
在某些时候,即使没有圆括号, Python仍然可以根据上下文认出这是一个元组,如: (为了写出更清晰可读的程序,建议你不要依赖 Python 的智能)

a = 1,4,5,-9,10
b = 7,
person = first_name, last_name, phone
元组支持大多数列表的操作,比如索引,切片和连结。一个关键的不同是你不能在一个tuple创建之后修改它的内容。也就是说,你不能修改其中的元素,也不能给tuple添加新的元素。


1.7. 循环
通过使用while语句,我们在前面已经简单介绍了 while 循环。在Python中另一种循环结构是 for 循环,它通过 迭代 一个序列(例如字符串,列表,或者tuple等)中的每个元素来建立循环。下边是一个例子:

for i in range(1,10):
        print "2 to the %d power is %d" % (i, 2**i)
range(i,j)函数建立一个整数序列,这个序列从第 i 数开始(包括 i )到第 j 数为止(不包括 j)。若第一个数被省略,它将被认为是0。该函数还可以有第三个参数,步进值,见下面的例子:

a = range(5)         # a = [0,1,2,3,4]
b = range(1,8)       # b = [1,2,3,4,5,6,7]
c = range(0,14,3)    # c = [0,3,6,9,12]
d = range(8,1,-1)    # d = [8,7,6,5,4,3,2]
for语句可以迭代任何类型的序列:

a = "Hello World"
# Print out the characters in a
for c in a:
        print c
b = ["Dave","Mark","Ann","Phil"]
# Print out the members of a list
for name in b:
        print name
range()函数根据起始值,终止值及步进值三个参数在内存中建立一个列表,当需要一个很大的列表时,这个既占内存又费时间。为了克服它的缺点,Python提供了xrange()函数:

for i in xrange(1,10):
        print "2 to the %d power is %d" % (i, 2**i)

a = xrange(100000000)       # a = [0,1,2, ..., 99999999]
b = xrange(0,100000000,5)   # b = [0,5,10, ...,99999995]
xrange()函数只有在需要值时才临时通过计算提供值,这大大节省了内存。


1.8. 字典
字典就是一个关联数组(或称为哈希表)。它是一个通过关键字索引的对象的集合。使用大括号{}来创建一个字典,如下 例:

a = {
       "username" : "beazley",
       "home" : "/home/beazley",
       "uid" : 500
    }

用关键字索引操作符可以访问字典的某个特定值:

u = a["username"]
d = a["home"]

用下面的方式插入或者修改对象:

a["username"] = "pxl"
a["home"] = "/home/pxl"
a["shell"] = "/usr/bin/tcsh"
尽管字符串是最常见的 关键字(key) 类型,你还是可以使用很多其它的 python 对象做为字典的关键字,比如 数字 和 tuple,只要是不可修改对象,都可以用来做字典的key。有些对象,例如列表和字典,不可以用来做字典的key,因为他们的内容是允许更改的。

我们可以使用 has_key() 方法来检验一个键/值对是否存在(或者in操作符):

if a.has_key("username"):
     username = a["username"]
else:
     username = "unknown user"

上边的操作还可以用更简单的方法完成:

username = a.get("username", "unknown user")

字典的keys() 方法返回由所有关键字组成的列表:

k = a.keys()         # k = ["username","home","uid","shell"]

del语句可以删除字典中的特定元素:

del a["username"]

1.9. 函数
在Python中,使用def语句来创建函数,如下例:

def remainder(a,b):
        q = a/b
        r = a - q*b
        return r
要调用一个函数,只要使用函数名加上用括号括起来的参数就可以了。比如result = remainder(37,15),如果你打算让函数返回多个值,就让它返回一个元组好了。(当然,只要你愿意,让它返回一个列表我们也不会介意)

def divide(a,b):
        q = a/b        # If a and b are integers, q is an integer
        r = a - q*b
        return (q,r)
当返回一个 tuple 时,你会发现象下面这样调用函数会很有用:

quotient, remainder = divide(1456,33)

你也可以象下面这样给函数的参数指定一个默认值:

def connect(hostname,port,timeout=300):
      # Function body
若在函数定义的时候提供了默认参数,那么在调用函数时就允许省略这个参数:

connect('www.python.org', 80)

你也可以使用关键字参数来调用函数,这样你的参数就可以使用任意顺序:

connect(port=80,hostname="www.python.org")

函数内部定义的变量为局部变量,要想在一个函数内部改变一个全局变量的值,在函数中使用global语句:

切换行号显示
   1 a = 4.5
   2 ...
   3 def foo():
   4         global a
   5         a = 8.8             # 改变全局变量 a

1.10. 类
Python支持面向对象编程,在面向对象编程中,class语句用于定义新类型的对象。例如,下面这个类定义了一个简单的堆栈:

切换行号显示
   1 class Stack(object):
   2         def __init__(self):              # 初始化栈
   3                 self.stack = [ ]
   4         def push(self,object):
   5                 self.stack.append(object)
   6         def pop(self):
   7                 return self.stack.pop()
   8         def length(self):
   9                 return len(self.stack)
在类定义中,方法用 def 语句定义。类中每个方法的第一个参数总是引用类实例对象本身,大家习惯上使用 self 这个名字代表这个参数。不过这仅仅是个习惯而已,如果你愿意也可以用任意的别的名字。不过为了别人容易看懂你的程序,最好还是跟随大家的习惯。类的方法中若需要调用实例对象的属性则必须显式使用self变量(如上所示)。方法名中若前后均有两个下划线,则表示这是一个特殊方法,比如init方法被用来初始化一个对象(实例)。

象下面这样来使用一个类:

切换行号显示
   1 s = Stack()           # Create a stack (创建)
   2 s.push("Dave")        # Push some things onto it (写入)
   3 s.push(42)
   4 s.push([3,4,5])
   5 x = s.pop()           # x gets [3,4,5] (读取)
   6 y = s.pop()           # y gets 42
   7 del s                 # Destroy s (删除)

1.11. 异常
如果在你的程序发生了一个错误,就会引发异常(exception),你会看到类似下面的错误信息:

Traceback (most recent call last):
File "<interactive input>", line 42, in foo.py
NameError: a
错误信息指出了发生的错误类型及出错位置,通常情况下,错误会导致程序终止。不过你可以使用 try 和 except 语句来捕获并处理异常:

try:
    f = open("file.txt","r")
except IOError, e:
    print e
上面的语句表示:如果有 IOError 发生,造成错误的详细原因将会被放置在对象 e 中,然后运行 except 代码块。 若发生其他类型的异常,系统就会将控制权转到处理该异常的 except 代码块,如果没有找到该代码块,程序将运行终止。若没有异常发生,except代码块就被忽略掉。

raise语句用来有意引发异常,,你可以使用内建异常来引发异常,如下例:

raise RuntimeError, "Unrecoverable error"

当然,你也可以建立你自己的异常,这将在 第五章--控制流中的定义新的异常中详细讲述。


1.12. 模块
当你的程序变得越来越大,为了便于修改和维护,你可能需要把它们分割成多个相关文件。 Python允许你把函数定义或公共部分放入一个文件,然后在其他程序或者脚本中将该文件作为一个模块导入。要创建一个模块,把相应的语句和定义放入一个文件,这个文件名就是模块名。(注意:该文件必须有.py后缀):

切换行号显示
   1 # file : div.py
   2 def divide(a,b):
   3     q = a/b        # If a and b are integers, q is an integer
   4     r = a - q*b
   5     return (q,r)
要在其它的程序中使用这个模块,使用import语句:

import div
a, b = div.divide(2305, 29)
import语句创建一个新的名字空间,该空间包含模块中所有定义对象的名称。要访问这个名字空间,把模块名作为一个前缀来使用这个模块内的对象,就像上边例子中那样:div.divide()

如果你希望使用一个不同的模块名字访问这个模块,给import语句加上一个 as 模块名 部分就可以了:

import div as foo
a,b = foo.divide(2305,29)

如果你只想导入指定的对象到当前的名称空间,使用 from 语句:

from div import divide
a,b = divide(2305,29)       # No longer need the div prefix (不再需要div前缀)

导入一个模块中的所有内容到当前的名称空间:

from div import *

最后,内建函数dir()可以列出一个模块中的所有可访问内容。当你在python交互环境中测试一个模块的功能时,这会是一个很有用的工具,因为它可以提供一个包含可用函数及变量的列表:

>>> import string
>>> dir(string)
['_ _builtins_ _', '_ _doc_ _', '_ _file_ _', '_ _name_ _', '_idmap',
'_idmapL', '_lower', '_swapcase', '_upper', 'atof', 'atof_error',
'atoi', 'atoi_error', 'atol', 'atol_error', 'capitalize',
'capwords', 'center', 'count', 'digits', 'expandtabs', 'find',
...
>>>
顶部

正在浏览此帖的会员 - 共 9 人在线




当前时区 GMT+8, 现在时间是 2024-11-19 14:40
京ICP备2023018092号 轩辕春秋 2003-2023 www.xycq.org.cn

Powered by Discuz! 5.0.0 2001-2006 Comsenz Inc.
Processed in 0.016874 second(s), 9 queries , Gzip enabled

清除 Cookies - 联系我们 - 轩辕春秋 - Archiver - WAP