Thinking In Python(Bruce Eckel) 程序员的Python快速入门

程序员的Python快速入门
 
本书面向经验丰富的程序员,如你已经通过其他书记学习了python则更佳。对于其他读者,这里提供了一个python语言快速指引。
Pythong综述

  这是面向有经验的程序员(你阅读此书时应该达到的水平)做的Python的简要介绍。你可以参考 [url]www.Python.org[/url]上的关于Python的全套文档(尤其是极其有用的HTML文档 A Python Quick Reference),还有其他著作如Mark Lutz和David Ascher的《Learning Python》(O'Reilly,1999)。
  Python通常被认为是一种脚本语言,但是脚本语言在功能上非常受限,从另一方面讲,Python是一种支持脚本的编程语言。它是一个神奇的脚本,以致你可能会把你所有的批处理文件,脚本文件和其他简单程序都换成Python脚本。尽管如此,Python最非仅仅是一个脚本语言。
 
  使用Python写程序非常优雅而且可读性好。你可以毫不费力的阅读你很久以前编写的python代码,或者他人的代码。这要归功于简单明了的语法,但为代码的可读性做最大贡献的是代码缩进--Python代码的作用域是由缩进决定。
#: c01:if.py
response = "yes"
if response == "yes":
  print "affirmative"
  val = 1
print "continuing..."
#:~
和C++/Jave中的'//'类似,Python使用'#'来注释代码。从'#'到行末都是注释。

从if语句看Python的语法很像C。在C中你需要使用括号来包着if条件,Python无需这样做(如果你执意要这样做也没问题)。

条件子句用:结束,后面跟着一组缩进了的语句,如果if条件成立就执行这组语句。在这个例子中,print语句把结果送至标准输出,然后向变量val赋值。后面一个不带缩进的print语句就不是if子句的一部分了。缩进可以无限嵌套下去,类似C++和Java中的花括号,但和这些语言不同的是再也不需要关心把花括号的位置,编译器强制代码必须使用缩进风格。这就是Pyhon代码的可读性好的主要原因。
Pyhon通常一行一个语句(一行多个语句使用分号分开),所以结尾分号是多余的。从上面的简单例子看,作者力求把Python设计得尽量简洁而又不失可读性。
 
 
内置的容器对象

  C++和Java的容器对象通常是附加库而非语言本身的组成部分。Python非常重视容器对象,在语言中内置了容器对象:包括列表和关联数组(maps,dictionaries, hash tables)都是基础数据类型。这些使的语言更加优雅。
  特别地,for语句可以自动迭代一个list而不需使用顺序数字来访问。如果你只想用一个for循环遍历一次容器内的所有对象,这样所是很有意义的。Python使用自动的迭代器来遍历整个列表。如下面例子:
#: c01:list.py
list = [ 1, 3, 5, 7, 9, 11 ]
print list
list.append(13)
for x in list:
  print x
#:~

  第一句创建一个list。输出该列表验证一下和你放入列表中的对象是否一致(作为对比,曾记得我在Think in Java第二版中特意为输出数组创建了Array2类)。list很像Java容器--可以添加对象(使用append()函数),容器大小会自动增长。 该for语句创建了一个可以遍历list迭代器x。
 
  range()函数可以创建一个由数组组成的list。如果确实需要模仿c数组,你可以这样做。
  你是否注意这里未曾看到类型定义?实际上Python根据变量的使用方式来确定它们的类型。似乎作者把Python设计成这样的一个语言:你在键盘的每个敲打动作都是必须的。使用Python一段时间后会发现你以前把太多的脑细胞绞杀于解释分号、花括号以及各种零碎中去了,而这都是那些非Python式的编程语言所要求的,尽管它们无助于解决你的实际问题。
 

函数

  使用def关键字来定义函数,后面跟随函数名和参数列表。行尾使用':'来分开函数体。
如下例声明函数:
#: c01:myFunction.py
def myFunction(response):
  val = 0
  if response == "yes":
    print "affirmative"
    val = 1
  print "continuing..."
  return val
print myFunction("no")
print myFunction("yes")
#:~
 
  值得注意的是函数没有任何函数签名--我们指示了函数名和参数,没有明示参数类型和返回值的类型。这又最大限度的节省了打字动作。例如,你可以使同一函数,传递不同的类型参数,获得不同类型的返回值:
#: c01:differentReturns.py
def differentReturns(arg):
  if arg == 1:
    return "one"
  if arg == "one":
    return 1
print differentReturns(1)
print differentReturns("one")
#:~
 
  对参数的唯一要求是:该参数对象必须支持函数中对其进行的操作,其他问题就无关重要了。这里有一个函数对整数和字符串进行'+'运算。

#: c01:sum.py
def sum(arg1, arg2):
  return arg1 + arg2
print sum(42, 47)
print sum('spam ', "eggs")
#:~

  对于字符串,'+'表示串连接(Python很好地支持运算符重载)。
 
 
字符串

上面例子显示了一点Python的字符串操作,这是我见过最好的编程语言。你可以使用单引号和双引号来表示字符串,这是非常优雅的:你可以在单引号限定的字符串中包含双引号,反之亦然。

#: c01:strings.py
print "That isn't a horse"
print 'You are not a "Viking"'
print """You're just pounding two
coconut halves together."""
print '''"Oh no!" He exclaimed.
"It's the blemange!"'''
print r'c:\python\lib\utils'
#:~
 
  须知Python并不是得名于蟒蛇,而是得名于Monty Python马戏团。
  用三个双引号(""")来限定的字符串可以包含一切东西,包括换行符。对于生成一个网页(Python非常适于CGI编程)这种需求很有用,你可以用三引号来包住整个html页面而不需任何其他转义。
 
  'r'引导的字符串表示原始串,串内所有字符都不需转义。这样你无需把'\'表示为'\\'。
 
  字符串模板替换很简单,Python基本沿用了C的printf语法。你可以简单地在字符串模板后使用'%'和对应的值来实现模板替换。
 
#: c01:stringFormatting.py
val = 47
print "The number is %d" % val
val2 = 63.4
s = "val: %d, val2: %f" % (val, val2)
print s
#:~
 
  在第二个例子中,如果你有超过一个的参数要替换,请用括号把参数包起来(以tuple的形式表示,不可修改;也可以使用常规的list对象,但tuple更常用)。

  printf的所有格式控制方式都支持,包括小数点位置和对齐。Python也实现了非常精巧的正则表达式。
 

类定义
 
  以Python一贯的作风,类的定义也尽量使用了最精简的语法。使用class关键字,在类体内用def创建类方法。例如:
 
#: c01:SimpleClass.py
class Simple:
  def __init__(self, str):
    print "Inside the Simple constructor"
    self.s = str
  # Two methods:
  def show(self):
    print self.s
  def showMsg(self, msg):
    print msg + ':',
    self.show() # Calling another method
if __name__ == "__main__":
  # Create an object:
  x = Simple("constructor argument")
  x.show()
  x.showMsg("A message")
#:~

  所有的方法都有把self作为第一个参数。C++和Java类函数也有一个相应隐藏的参数this,该this参数指向调用该函数的对象。Python方法也保存当前对象的引用,不过该引用在定义类函数的时候必须显式声明该引用为第一个参数。通常地,该参数命名为self,但你可以使用其他标识符(但不使用self可能会令你的代码阅读者感到困惑)。如果你需要引用对象中的成员(field)或者方法(method),必须在表达式中使用self参数。当然,调用一个对象的方法仍然是用x.show()形式,无需传入该对象的引用--这部分工作已经自动完成了。
 
  此处,类的第一个方法是很特殊的,这种方法的名称以两个下划线开头。在这个例子中,它定义了构造函数。类似C++/Java,构造函数在对象创建时被调用。在本例末尾,你可以看到创建一个对象就好像调用一个函数一样。Python的特别语法让人觉得C++/Java new关键字根本就是多余的。

  例子末尾的代码由一个if子句开始。该if子句检查__name__变量是否为"__main__"。两个下划线开始的标识符表示特殊名字。使用if的原因是:任何文件都可以作为其他程序的一个库模块(或简称模块)。在这个例子中,你只需要定义一个类,并不需要执行后面的代码。这个特别的if子句在直接运行本文件的时候才会为True,即是你在命令行直接调用它:
Python SimpleClass.py
 
  然而,如果这个文件被导入到其他程序中,__main__部分代码是不执行的。
令人觉得惊奇的是在方法的内部定义成员,而不像C++/Java一样在方法的外部(如果你像C++/Java一样在外部声明成员,它们默认为static成员)。为了创建一个成员,你需要用在任何方法(通常是构造函数,但不绝对)内使用self来引用它,当方法被调用时分配内存空间。对于C++/Java来说这有点诡异,在C++/Java中你必须事先决定你的类对象需要使用多少存储空间,但Python的做法更有弹性。
 
 
继承

  Python是是弱类型检查的,它不关注接口,只关注把操作施加于对象(Java的interface关键字在Python中多余)。这意味着Python的继承和C++/Java是不同的,它们的继承是为了确认一个公共接口。在Python中,你使用继承的唯一原因是你需要继承一个实现--为了重用基类已有代码(而非定义统一接口,译者注)。
 
  如果你要继承一个类,必须告诉Python把该类导入到你的新文件中。和Java类似,Python对它的命名空间控制得很强(尽管Python追求简约)。当你新建一个文件,你需要隐式创建一个和文件名同名的模块(类似Java中的package)。所以,Python没有package关键字。当你需要使用一个模块时,你只需要导入并命名模块。Python搜索PYTHONPATH系统变量指示的路径得到所需模块,如同Java对CLASSPATH一样(但Python摆脱了这个机制的某些缺陷)。为了引用模块中的函数和类,使用模块名加一个点再加函数名或类名即可。如果觉得引用模块名很麻烦,你可以写 from module import name(s)
  "name(s)"可为逗号分割的一个列表
  引用一个类(或多个类,Python支持多重继承)的方法是把类名写在你的类名后的括号里。使用import把文件SimpleClass中的类Simple被导入到新命名空间:
#: c01:Simple2.py
from SimpleClass import Simple
class Simple2(Simple):
  def __init__(self, str):
    print "Inside Simple2 constructor"
    # You must explicitly call
    # the base-class constructor:
    Simple.__init__(self, str)
  def display(self):
    self.showMsg("Called from display()")
  # Overriding a base-class method
  def show(self):
    print "Overridden show() method"
    # Calling a base-class method from inside
    # the overridden method:
    Simple.show(self)
class Different:
  def show(self):
    print "Not derived from Simple"
if __name__ == "__main__":
  x = Simple2("Simple2 constructor argument")
  x.display()
  x.show()
  x.showMsg("Inside main")
  def f(obj): obj.show() # .e-line definition
  f(x)
  f(Different())
#:~
  Simple2 继承了Simple, 在构造函数中初始化基类。display( ), showMsg( ) 都成self的方法, 但如果你想调用基类版本的方法,必须加入类名并传入self参数。参见构造函数和show方法。

  在__main__后,如同你所预期的一样,可以见到(运行该程序时)基类的构造函数被调用,showMsg函数在子类中可用。
  类Differential也有一个showMsg方法,但不是从Simple继承来的。__main__中的f()演示了弱类型检查:它只关注show()能否被施加于obj,而不管对象是何种类型。你可以看到f()可以不加区别用于Simple类对象或者其他对象,不论它们从何而来。如果你是C++程序员,应该知道这就是C++ template的特性:在强类型的语言中加入弱化类型检查。这样,在Python中你可以自动得到模板的实现而不需拘泥于特别的语法语义。

 

你可能感兴趣的:(入门,python,in,think,简约)