Ruby是什么意思。。

Python017

Ruby是什么意思。。,第1张

Ruby,一种简单快捷的面向对象(面向对象程序设计)脚本语言,在20世纪90年代由日本人松本行弘(Yukihiro Matsumoto)开发,遵守GPL协议和Ruby License。

Ruby的变量有一定的规则,以$开头的一定是全局变量,以@开头的都是实例变量,而以@@开头的是类变量。

常数则以大写字母开头这种方法,对文本编辑器的命令补全很有帮助,如在vim下先键入$及开头字母,再敲击Ctrl+p,则可专门补全本文件以及关联文件中的全局变量,perl与php亦有此优点。

已经定义的类可以在运行时修改

Ruby是动态语言,你可以在程序中修改先前定义过的类。 也可以在某个类的实例中定义该实例特有的方法,这叫做单例方法。

使用Ruby可以写出简短而又功能强大的代码

下面的方法用来完成两个矩阵的乘积

注:ruby标准库中已包含矩阵库 Matrix

Ruby是一个完美的面向对象编程语言。拥有面向对象的编程语言的功能,包括:

1、数据封装

2、数据抽象

3、多态性

4、继承

这些功能已在讨论面向对象Ruby

面向对象的程序涉及类和对象。 一个类是蓝本,从个别对象被创建。在面向对象的术语,我们说小明的自行车是被称为自行车类的对象实例。

任何车辆的例子。它包括轮子,马力,燃油或燃气罐容量。这些特点形成的类车辆的数据成员。可以从其他车辆区分这些特征。

车辆也有一定的功能,如停止,驾驶,超速驾驶。即使这些功能形成的类车辆的数据成员。因此,可以定义一个类作为一个组合的特点和功能。

车辆类可以被定义为:

Class Vehicle

{

Number no_of_wheels

Number horsepower

Characters type_of_tank

Number Capacity

Function speeding

{

}

Function driving

{

}

Function halting

{

}

}

通过这些数据成员分配不同的值,可以形成类车辆的几个实例。例如,飞机的有三个轮子,1,000马力,不同的燃料罐及容量为100升。同样的方式,一辆汽车有四个轮子,200马力,气体作为不同的罐及容量25升。

Ruby中定义一个类:

要通过使用Ruby实现面向对象编程,需要先学习如何创建对象和Ruby中的类。

Ruby中一个类总是以关键字class类的名称开头。名称应始终以首字母大写。如以是Customer类可以显示为:

class Customer

end

类定义结束通过使用关键字end结束。在类的所有数据成员是类之间的定义,并以end关键字作为结束符。

Ruby类中的变量:

Ruby提供了四种类型的变量:

局部变量: 局部变量是在一个方法中定义的变量。局部变量是不可用的方法外。更多细节在随后的章节中的方法中会介绍。局部变量一般以小写字母或_开头。

实例变量: 实例变量是可跨越任何特定实例或对象的方法。这意味着,从对象到对象的实例变量改变。实例变量前面加上at符号(@),跟着变量名。

类变量:类变量是可在各种不同的对象。 一个类变量属于类,是类的一个特点。他们前面的符号@@跟着的变量名。

全局变量: 类变量是不能跨类。如果想要一个单一的变量可以跨类,需要定义一个全局变量。全局变量的前面总是用美元符号($)。

例子:

使用类变量@@no_of_customers,能确定创建的对象的数量。这使得导出的客户数量。

class Customer

@@no_of_customers=0

end

Ruby中使用new方法创建对象:

对象是类的实例。现在,将学习如何在Ruby中创建对象一个类对象。Ruby中通过使用new方法创建对象。

new方法是一种独特的方法,这是预定义在Ruby库。new方法属于类的方法。

下面的例子是创建两个对象类客户cust1 和 cust2:

cust1 = Customer. new

cust2 = Customer. new

在这里,cust1和cust2是两个对象的名字。在等于号(=)之后,类名称将按照对象名称。然后,点运算符和关键字new在后面。

自定义方法来创建Ruby对象 :

可以通过new方法的参数,这些参数可以用来初始化类变量。

当打算声明的new方法具有参数,需要声明的方法在创建类的时候初始化。

initialize方法是一种特殊类型的方法,该方法时将执行new方法的类被称为参数。

下面的例子是创建initialize方法:

class Customer

@@no_of_customers=0

def initialize(id, name, addr)

@cust_id=id

@cust_name=name

@cust_addr=addr

end

end

在这个例子中,可以声明局部变量的初始化方法id, name和addr。这里def 结束被用来定义一个Ruby的方法初始化。这些将在有关后续章节中了解更多。

在initialize方法中,对这些局部变量的值传递到实例变量@cust_id,@cust_name和@cust_addr。这里的局部变量持有的值由new方法一同传递。

现在可以创建对象,如下所示:

cust1=Customer.new("1", "John", "Wisdom Apartments, Ludhiya")

cust2=Customer.new("2", "Poul", "New Empire road, Khandala")

Ruby中类的成员函数:

在Ruby中,函数被调用的方法。在一个类中的每个方法的方法名用关键字def开始。

方法名总是以小写字母最好。你最终的方法Ruby中通过使用关键字end表示结束。

下面的例子是定义一个Ruby的方法:

class Sample

def function

statement 1

statement 2

end

end

这里statement1和statement2为函数体的一部分。这些statments可以是任何有效的Ruby语句。例如,我们可以在方法中打印Hello Ruby如下:

class Sample

def hello

puts "Hello Ruby!"

end

end

现在,在下面的例子Sample类创建一个对象,并调用hello方法,看到的结果:

#!/usr/bin/ruby

class Sample

def hello

puts "Hello Ruby!"

end

end

# Now using above class to create objects

object = Sample. new

object.hello

这将产生以下结果:

Hello Ruby!

1\模块

如果退出Python解释程序然后再进入,原有的定义(函数和变量)就丢失了。所以,如

果需要写长一点的程序,最好用一个文本编辑程序为解释程序准备输入,然后以程序文

件作为输入来运行Python解释程序,这称为准备脚本(script)。当你的程序变长时,

最好把它拆分成几个文件以利于维护。你还可能想在几个程序中都使用某个很方便的函

数,但又不想把函数定义赋值到每一个程序中。

为了支持这些,Python有一种办法可以把定义放在一个文件中然后就可以在一个脚本中

或交互运行中调用。这样的文件叫做一个模块;模块中的定义可以导入其它模块或主模

块(主模块指在解释程序顶级执行的脚本或交互执行的程序所能访问的变量集合)。

模块是包含了Python定义和语句的文件。文件名由模块名加上后缀“.py”构成。在模块

内,模块的名字(作为一个字符串)可以由全局变量__name__的值获知。例如,在Pyth

on的搜索路径中用你习惯使用的文本编辑器(Python 1.5.2包含了一个用Tkinter编写的

IDLE集成开发环境,MS Windows下有一个PythonWin界面也可以进行Python程序编辑)生

成一个名为“fibo.py ”的文件,包含如下内容:

# Fibonacci numbers module

def fib(n):# 输出小于n的Fibonacci序列

a, b = 0, 1

while b <n:

print b,

a, b = b, a+b

def fib2(n): # 返回小于n的Fibonacci序列

result = []

a, b = 0, 1

while b <n:

result.append(b)

a, b = b, a+b

return result

然后进入Python解释程序(在IDLE或PythonWin中可以直接进入解释程序窗口),用如下

命令可以导入模块:

>>>import fibo

这不会把模块fibo中的函数的名字直接引入当前的符号表,这只是把模块名fibo引入。

可以用模块名来访问其中的函数:

>>>fibo.fib(1000)

1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

>>>fibo.fib2(100)

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

>>>fibo.__name__

'fibo'

如果经常使用某个函数可以给它赋一个局部名字:

>>>fib = fibo.fib

>>>fib(500)

1 1 2 3 5 8 13 21 34 55 89 144 233 377

6.1 模块的进一步介绍

模块除了可以包含函数定义之外也可以包含可执行语句。这些可执行语句用来初始化模

块,它们只在模块第一次被导入时执行。

每个模块有自己私有的符号表,这个私有符号表对于模块中的所有函数而言却是它们的

全局符号表。因此,模块作者可以在模块中使用全局变量而不需担心与模块用户的全局

变量冲突。另一方面,如果你有把握的话也可以用访问模块中函数的格式,即modname.

itemname的方法来修改模块中的全局变量。

模块可以导入其它模块。我们通常把所有的导入语句放在模块(或脚本)的开始位置,

这不是规定要求的。导入的模块名放入模块的全局符号表中。

导入还有另一种用法,可以把模块中的名字直接导入使用者的符号表。例如:

>>>from fibo import fib, fib2

>>>fib(500)

1 1 2 3 5 8 13 21 34 55 89 144 233 377

这不会把模块名导入使用者的符号表中(例如,上面例子中fibo就没有定义)。

还有一种办法可以导入一个模块中定义的所有名字:

>>>from fibo import *

>>>fib(500)

1 1 2 3 5 8 13 21 34 55 89 144 233 377

这可以把模块中除了以下划线结尾的所有名字导入。

6.1.1 模块搜索路径

在导入名为spam的模块时,解释程序先在当前目录中寻找名为“spam.py”的文件,然后

从环境变量PYTHONPATH所定义的目录列表中寻找。PYTHONPATH的用法和可执行文件的搜

索路径PATH用法相同,都是一个目录列表。当PYTHONPATH未设置的时候,或者文件仍找

不到,则搜索继续在安装时设定的缺省路径搜索,在Unix中,这通常是“.:/usr/local

/lib/python” 。

实际上,模块是按变量sys.path指定的路径搜索的,此变量在解释程序启动时初始化为

包含输入脚本的目录(或当前路径),PYTHONPATH和安装缺省路径。这样,用户可以通

过修改sys.path 来修改和替换模块搜索路径。参见后面关于标准模块的一节。

6.1.2 “编译”的Python文件

为了提高调用许多标准模块的小程序的启动时间,一个重要的措施是,如果在找到“sp

am.py ”的目录中存在一个名为“spam.pyc”的文件,就认为此文件包含了模块spam的

一个所谓“ 字节编译”版本。用于生成“spam.pyc”的“spam.py”的修改时间被记入

了“spam.pyc”中,如果记录的修改时间与现在文件的时间不相符的话就忽略编译文件

一般不需要自己生成“spam.pyc”这样的编译文件。每当“spam.py”成功编译后解释程

序就尝试写编译版本“spam.pyc”,如果不可写也不会出错;如果因为某种原因此文件

没有写完则生成的“spam.pyc”被识别为不完整的而被忽略。编译文件“spam.pyc”的

格式是不依赖于平台的,所以不同结构的机器可以共享Python模块目录。

下面是对专家的一些窍门:

如果Python解释程序是以-O标志启动的,将生成优化的编译代码,保存在“.pyo”文件

中。目前优化不是很多,现在只是去掉assert语句和SET_LINENO指令。使用了-O标志时

,所有字节码都是优化的,“.pyc”文件被忽略,“.py”文件被编译为优化的字节码。

给Python解释程序两个优化标志(-OO)产生的优化代码有时会导致程序运行不正常。目

前双重优化只从字节码中删除了__doc__字符串,使得“.pyo”文件较小。有些程序可能

是依赖于文档字符串的,所以只有在确知不会有问题时才可以使用这样的优化。

从“.pyc”或“.pyo”读入的程序并不能比从“.py”读入的运行更快,它们只是调入速

度更快一些。

如果一个程序是用在命令行指定脚本文件名的方式运行的,脚本的字节码不会写入“.p

yc ”或“.pyo”文件。所以如果把程序的主要代码都移入一个模块,脚本中只剩下导入

该模块的引导程序则可以略微缩短脚本的启动时间。

可以有叫做“spam.pyc”(当用了-O标志时为“spam.pyo”)的文件而没有对应的源文

件“spam.py”。这可以用来分发一个比较难反编译的Python代码库。

模块compileall可以把一个目录中所有模块编译为“.pyc”文件(指定了-O选项时编译

为“.pyo”文件)。

6.2 标准模块

Python带有一个标准模块库,在另一个文档《Python库参考》中进行了描述。一些模块

直接编入了解释程序中,这些模块不是语言的核心,为了运行效率或者为了提供对于系

统调用这样的系统底层功能而编入了解释程序中。提供那些模块是编译时的选择,例如

,amoeba模块只在提供amoeba底层指令的系统中才能提供。

有一个模块值得特别重视:sys模块,每一个Python解释程序中都编译入了这个模块。变

量sys.ps1和sys.ps2定义了交互运行时的初始提示和续行提示。

>>>import sys

>>>sys.ps1

'>>>'

>>>sys.ps2

'... '

>>>sys.ps1 = 'C>'

C>print 'Yuck!'

Yuck!

C>

这两个变量只在解释程序以交互方式运行时才有定义。

变量sys.path是一个字符串列表,由它确定解释程序的模块搜索路径。它被初始化为环

境变量PYTHONPATH所指定的缺省路径,环境变量没有定义时初始化为安装时的缺省路径

。可以用标准的列表操作修改这个搜索路径,例如:

>>>import sys

>>>sys.path.append('/ufs/guido/lib/python')

6.3 dir()函数

内置函数dir()用于列出一个模块所定义的名字,它返回一个字符串列表:

>>>import fibo, sys

>>>dir(fibo)

['__name__', 'fib', 'fib2']

>>>dir(sys)

['__name__', 'argv', 'builtin_module_names', 'copyright', 'exit',

'maxint', 'modules', 'path', 'ps1', 'ps2', 'setprofile', 'settrace',

'stderr', 'stdin', 'stdout', 'version']

没有自变量时,dir()列出当前定义的名字。

>>>a = [1, 2, 3, 4, 5]

>>>import fibo, sys

>>>fib = fibo.fib

>>>dir()

['__name__', 'a', 'fib', 'fibo', 'sys']

注意dir()列出了所有各类名字:变量名、模块名、函数名,等等。dir()不会列出内置

函数、变量的名字。要想列出内置名字的话需要使用标准模块__builtin__:

>>>import __builtin__

>>>dir(__builtin__)

['AccessError', 'AttributeError', 'ConflictError', 'EOFError', 'IOError',

'ImportError', 'IndexError', 'KeyError', 'KeyboardInterrupt',

'MemoryError', 'NameError', 'None', 'OverflowError', 'RuntimeError',

'SyntaxError', 'SystemError', 'SystemExit', 'TypeError', 'ValueError',

'ZeroDivisionError', '__name__', 'abs', 'apply', 'chr', 'cmp', 'coerce',

'compile', 'dir', 'divmod', 'eval', 'execfile', 'filter', 'float',

'getattr', 'hasattr', 'hash', 'hex', 'id', 'input', 'int', 'len', 'long',

'map', 'max', 'min', 'oct', 'open', 'ord', 'pow', 'range', 'raw_input',

'reduce', 'reload', 'repr', 'round', 'setattr', 'str', 'type', 'xrange']

6.4 包

Python中可以用“包”来组织Python的模块名字空间,名字引用时可以用“带点的模块

名。例如,模块名A.B代表包“A”内名为“B”的子模块。正如使用模块可以使不同模块

的作者不用顾虑彼此的全局变量名会冲突,使用带点的模块名可以使多模块包如NumPy和

PIL的作者不需要担心彼此的模块名会冲突。

假设你有一系列处理声音文件和声音数据的模块(称为一个“包”)。有许多种不同的

声音文件格式(通常用扩展名来识别,如“wav”,“.aiff”,“.au”),所以你可能

需要制作并维护一组不断增加的模块来处理不同文件格式的转换。你还可能需要对声音

数据进行许多不同的操作(如混音、回响、均衡、产生模拟立体声效果),所以你还需

要不断增加模块来执行这些操作。一下是你的程序包的可能的结构(用一个分层文件系

统表示):

Sound/ 顶层包

__init__.py 初始化音响包

Formats/ 用于文件格式转换的子程序包

__init__.py

wavread.py

wavwrite.py

aiffread.py

aiffwrite.py

auread.py

auwrite.py

...

Effects/ 用于音响效果的子程序包

__init__.py

echo.py

surround.py

reverse.py

...

Filters/ 用于滤波的子程序包

__init__.py

equalizer.py

vocoder.py

karaoke.py

...

包目录中的“__init__.py”文件是必须得,用来指示Python把这个目录看成包,这可以

防止有相同名字如“string”的子目录掩盖住在搜索路径后面一些出现的模块定义。在

最简单的情况下,“__init__.py”可以是一个空文件,它也可以包含初始化包所需的代

码,和设置“__all__”变量,这些后面会加以讨论。

包的用户可以从包中导入单独的模块,如:

import Sound.Effects.echo

这可以把子模块Sound.Effects.echo导入。要引用它也必须用全名,例如:

Sound.Effects.echo.echofilter(input, output, delay=0.7, atten=4)

导入子模块的另一种办法是:

from Sound.Effects import echo

这同样也导入子模块echo,但调用时不需写包前缀,所以可以用如:

echo.echofilter(input, output, delay=0.7, atten=4)

另外一种写法是直接导入所需的函数或变量:

from Sound.Effects.echo import echofilter

这一次同样是调入了子模块echo,但是使其函数echofilter直接可用:

echofilter(input, output, delay=0.7, atten=4)

注意使用“from 包 import 项”这样的格式时,导入的项可以是包的一个子模块(或子

包),也可以是包内定义的其它名字如函数、类、变量。导入语句首先查找包内是否定

义了所需的项,如果没有则假设它是一个模块然后调入。如果找不到,结果引起Import

Error。

相反的,当使用“import item.subitem.subsubitem”这样的格式时,除最后一个外其

它各项都应该是包,最后一项可以是包也可以是模块,不允许是前面一项内部定义的类

、函数或变量。

6.4.1 从包中导入*

现在,如果用户写“from Sound.Effects import *”会发生什么情况?理想情况下我们

希望这应该扫描文件系统,找到所有包内的子模块并把它们都导入进来。不幸的是这种

操作在Mac和Windows平台上不能准确实现,这两种操作系统对文件名的大小写没有准确

信息。在这些平台上,不知道名为“ECHO.PY”的文件会作为模块echo、Echo还是ECHO被

导入。(例如,Windows 95在显示文件名时总是讨厌地把第一个字母大写)。DOS的8+

3文件名限制更是对长模块名造成了有趣的困难。

这个问题的唯一解决办法是由模块作者显式地提供包的索引。引入*的import语句遵循如

下规定:如果包的“__init__.py”文件定义了一个名为“__all__”的列表,这个列表

就作为从包内导入*时要导入的所有模块的名字表。因此当包的新版本发布时需要包的作

者确保这个列表是最新的。包的作者如果认为不需要导入*的话也可以不支持这种用法。

例如,文件Sounds/Effects/__init__.py 可以包含如下代码:

__all__ = ["echo", "surround", "reverse"]

这意味着from Sound.Effects import *将从Sound包中导入指定的三个子包。

如果没有定义__all__,则from Sound.Effects import *语句不会导入Sound.Effects包

中的所有子模块;此语句只能保证Sound.Effects被导入(可能是执行其初始化代码“_

_init__.py ”)并导入包中直接定义的名字。这包括由“__init__.py”定义的任何名

字和显式导入的子模块名。这也包括模块中已经在前面用import显式地导入的子模块,

例如:

import Sound.Effects.echo

import Sound.Effects.surround

from Sound.Effects import *

在这个例子中,echo和surround模块被导入当前名字空间,因为它们在执行from...imp

ort 语句时已定义(在定义了__all__的情况下这一点也是成立的)。

注意用户应尽量避免使用从模块或包中导入*的做法,因为这样经常导致可读性差的代码

。尽管如此,在交互运行时可以用导入*的办法节省敲键次数,而且有些模块在设计时就

考虑到了这个问题,它们只输出遵循某种约定的名字。注意,from 包 import 特定子模

块的用法并没有错,实际上这还是我们推荐的用法,除非程序还需要用到来自其它包的

同名的子模块。

6.4.2 包内部引用

子模块常常需要彼此引用。例如,模块surround可能要用到模块echo。事实上,这样的

引用十分常见,所以import语句首先从子模块的所在包中寻找要导入的子模块才在标准

模块搜索路径查找。所以,模块surround只要写import echo或from echo import echo

filter。如果在包含本模块的包中没有找到要导入的模块,import语句将去寻找指定名

字的顶级模块。

当包组织成子包时(比如例中的Sound包),没有一种简单的办法可以引用兄弟包中的子

模块――必须使用子模块的全名。例如,如果模块Sound.Filters.vocoder要引用Sound

.Effects 包中的echo模块,它可以用Sound.Effects import echo。

通过执行类代码体创建或扩展类Class的对象

ruby 代码

class [scope::] classname [

body

end

注意:

1、如果superexpr存在,那么该superexpr应当是一个以Class对象为结果的表达式,而且它将是被定义的类的超类。

如果省略superexpr,则默认为类Object

2、所有类定义是在代码执行时候生成的。

3、所有类定义在执行后都是一个Class类的对象。

4、所有的这些对象都将赋给名为classname的常量。

5、使用域作用符(::)可以为类定义中的classname前置一个已存在的类或模块名。这样会将新的定义插入到前面定义

的模块和/或类的名字空间中,但不是在这些外部类的作用域中解释此定义。前面带有域作用符的classname将被放置在

那个类或模块所处的顶层(这样作有个什么好处)

方式二、匿名类

ruby 代码

class <<obj

body

end

该类是一个匿名类,将会和指定的对象关联。这时这个匿名类将是该关联对象的虚拟类,原来该对象的类,变成了该虚拟 类的超类。

注意:如果直接在类定义外,给你对象新增一些方法和这样为一个对象创建一个类是等价的。同样是创建一个虚拟类。

Ruby类定义和其他语言不一样,其他语言都是在编译期处理的。而ruby是在代码运行时候根据类的定义创建的。这样如下特点:

1、可以在运行时候决定类的定义。这样根据不同条件,得出不同的类的定义结构

2、如果类定义是可执行的代码,那么它一定是在某个对象的上下文中执行的。Ruby中直接把该类作为当前对象

3、这个对象的类属于Class。说明,所有创建类就是一个对象,他们的类就是Class

太多了!对不起!没有给您找完