Python的入门简介

Python的入门简介

前段时间老板要做一个项目,采用的开发语言是Python,之前本人只学习过C++和Java两种传统的编程语言,对于Python语言的了解仅限于听说过而已,在参与这个项目过程中,真真实实感受到了Python语言的简单易用和它的快速开发的效率。
    我想可能部分网友和我有着相似的学习背景(只学习过传统的C++/Java编程语言,而对Perl/Python/Ruby没有了解),经历这个项目后,我认为像Python这样的语言确实有学习的必要,因此把我的Python学习笔记贴出来,不过前面部分写的过于基础了。

目录
1、第一个Python脚本: hello world
2、Python语言与传统的C++/Java语言显著不同的地方
3、Python语言的控制结构
4、变量声明和定义  
5、函数  
6、列表、字典、元组  
7、字符串处理
8、面向对象编程:封装、继承、虚拟函数、接口、多继承、模板
9、面向对象编程:异常处理

1、第一个Python脚本: hello world

[Copy to clipboard] [ - ]
CODE:
#!/usr/bin/python
print 'hello world'

与C语言的不同地方在于:
  • 不需要使用 ; 结尾
  • 不需要使用 () 把参数包起来
  • 可以使用单引号

这些做法可以使得程序看上去较为清爽,当然如果你不习惯的话,Python编译器也可以接受以下的风格

[Copy to clipboard] [ - ]
CODE:
#!/usr/bin/python
print("hello world");

2、Python语言与传统的C++/Java语言显著不同的地方
  • 变量在使用之前无须声明

    [Copy to clipboard] [ - ]
    CODE:
    a = 1
    b = "hello world"

  • 使用 # 而不是//和/* ... */注释代码

    [Copy to clipboard] [ - ]
    CODE:
    c = a + b # this is comment

  • 表达式语句不需要使用 ; 结尾

    [Copy to clipboard] [ - ]
    CODE:
    a = a + 1
    b = b + 1

  • 函数调用时不需要使用 () 把参数包起来,if/while 中的也不需要使用()把条件表达式包起来

    [Copy to clipboard] [ - ]
    CODE:
    print "hello world"
    if a == b:
            print 'a == b'
    else:
            print 'a != b'

  • 引号有单引号、双引号、三引号三种形式,后面详述
  • 使用“缩进”而不是{}标志代码块,下面我们将详细讨论这样作的优缺点.

先看一个例子:

[Copy to clipboard] [ - ]
CODE:
a = 1
b = 2
c = 3
d = 3
if a == b:
        if c == d:
                print 'a == b && c == d'
else:
        print 'a != b'
# 程序运行结果:a != b

注意:
  • 缩进相同的语句处于同一个语法块中
  • 在if/else语句末尾有一个冒号,代表语法块的开始
  • python中提供了pass语句,该条语句表示一个空操作

    [Copy to clipboard] [ - ]
    CODE:
    a = 1
    b = 2
    if a == b:
            pass
    else:
            print 'a != b'        
    # 程序运行结果:a != b



Python语言这种做法的优点在于:
  • 省去{}或者begin/end,使得程序结构更为清晰(也许有人会有不同的观点):
  • 强制所有的Python程序都有着相同的风格,不会像在C语言中出现风格迥异的情况:

    [Copy to clipboard] [ - ]
    CODE:
    /* K&R的风格 */
    if (a > b) {
       printf("a > b")
    }

    /* 很多人喜欢的风格 */
    if (a > b)
    {
       printf("a > b")
    }

    /* EMACS编辑器的风格 */
    if (a > b)
      {
       printf("a > b")
      }

  • 避免了如下情况由于忘记{}而造成的错误

    [Copy to clipboard] [ - ]
    CODE:
    #include <stdio.h>

    int main()
    {
            int a, b, c, d;
            a = 1;
            b = 2;
            c = 3;
            d = 3;
            if (a == b)
                    if (c == d)
                            puts("a == b && c == d");
            else
                    puts("a != b");
            return 0;
    }

    从缩进来看,编写这段代码的程序员的本意是希望当a、b不相等时输出"a != b",但是程序运行时没有任何输出,和程序员期待的结果是不一样的。


Python语言这种做法的缺点在于:
  • python的代码一旦缩进乱了,无法重新格式化
  • 粘贴代码的时候,缩进会被破坏,不方便

这些缺点倒是可以接受,关键在于用户是否认同Python缩进的优点。
3、Python语言的控制结构
  • if 语句

    [Copy to clipboard] [ - ]
    CODE:
    a = 1
    b = 2
    if a < b:
            print 'a < b'
    elif a == b:
            print 'a == b'
    else:
            print 'a > b'

    注意:Python中提供了elif语句,是else if的缩写。

  • switch 语句
    python没有提供switch 语句,另外python也不提供++、--运算符。

  • while 语句

    [Copy to clipboard] [ - ]
    CODE:
    sum = 0
    i = 1
    while i < 101:
            sum += i
            i += 1
    else:
            print("LOOP IS OVER, i = %d" % i)  # 格式化字符串输出的细节在后面详述
    print("sum = %d" % sum)

    程序运行结果:
    LOOP IS OVER, i = 101
    sum = 5050

  • while循环中的else语句
    while循环中有一个可选的else语句,当循环没有被break中断而结束时,执行else后面的语句块,如果把程序改为:

    [Copy to clipboard] [ - ]
    CODE:
    sum = 0
    i = 1
    while i < 101:
            sum += i
            i += 1
            break
    else:
            print("LOOP IS OVER, i = %d" % i)
    print("sum = %d" % sum)

    程序运行结果变为:
    sum = 1

  • for 语句
    python中不提供C语言风格的for循环,如下代码段是不被接受的:

    [Copy to clipboard] [ - ]
    CODE:
    for (i = 1; i < 101; i += 1):
            sum += i

    要计算从1累加到100的和,通常使用如下方法:

    [Copy to clipboard] [ - ]
    CODE:
    sum = 0
    for i in range(1, 101):
            sum += i
    else:
            print "LOOP IS OVER, i = %d" % i
    print "sum is %d" % sum

    运行结果:
    LOOP IS OVER, i = 100
    sum = 5050
    这里需要注意的是:
    • range(start, end, step)接受了三个参数:以步长为step(缺省为1),产生从start(包含)开始到end(不包含)结束的一个序列。在这个例子中,start = 1, end = 101, step = 1(缺省值),产生了从1到100总计100个数。
    • 使用i变量遍历range产生的序列,循环执行100次,i的值依次为1、2、... 100。
    • for循环也有可选的else语句,功能和while循环中的else语句相同。


  • for 语句,指定range的step

    [Copy to clipboard] [ - ]
    CODE:
    for i in range(10, 0, -1):
            print i
    程序输出结果:
    10
    9
    8
    7
    6
    5
    4
    3
    2
    1

    在这个例子中,start = 10,  end = 0,  step = -1,程序的功能类似于如下C代码:

    [Copy to clipboard] [ - ]
    CODE:
    start = 10
    end = 0
    step = -1
    for (i = start; i > end; i += step)
            print(i)

4、变量声明和定义
  • 变量在使用之前无须声明

    [Copy to clipboard] [ - ]
    CODE:
    var = 1
    print var

  • 变量在使用之前必须定义

    [Copy to clipboard] [ - ]
    CODE:
    print var
    # 运行时刻出错,NameError: name 'var' is not defined

  • 定义变量时,可以获知变量的类型,需要记住列表、字典、元组使用不同的括号[]、{}、()

    [Copy to clipboard] [ - ]
    CODE:
    # 整数
    integer = 123         

    # 字符串
    string = "hello"         

    # 列表
    list = [1, 2, 3]

    # 字典
    dict = {1:2, 2:4, 3:6}   

    # 元组
    tuple = (1, 2, 3)        

  • 在函数中缺省访问的是局部变量,当使用global声明后,访问的才是全局变量

    [Copy to clipboard] [ - ]
    CODE:
    def func():
            g = 2  # 局部变量

    g = 1
    func()
    print(g)

    func中修改了局部变量g,没有影响全局变量g,输出结果为1

    [Copy to clipboard] [ - ]
    CODE:
    def func():
            global g
            g = 2  # 全局变量

    g = 1
    func()
    print(g)

    func中修改了全局变量g,输出结果为2
5、函数
  • 使用def定义函数

    [Copy to clipboard] [ - ]
    CODE:
    def add(a, b):
           return a + b

    print(add(1, 2))

    运行结果为3

  • 函数可以递归调用

    [Copy to clipboard] [ - ]
    CODE:
    def fact(n):
            if n == 0:
                    return 1
            else:
                    return n * fact(n - 1)
    print(fact(3))

    运行结果为6

  • 缺省参数

    [Copy to clipboard] [ - ]
    CODE:
    def func(a = 'a', b = 'b', c = 'c', d = 'd', e = 'e', f = 'f'):
            print a + b + c + d + e + f
    # 情况1:所有参数使用缺省值
    # 输出结果:abcdef
    func()

    # 情况2:前面的参数使用指定值,后面的参数使用缺省值
    # 输出结果:ABCdef
    func('A', 'B', 'C')

    # 情况3:任意指定哪些参数接受缺省值,哪些参数使用指定值
    # 输出结果:aBcDeF
    func(b = 'B', d = 'D', f = 'F')

  • 把所有的参数存放在数组中

    [Copy to clipboard] [ - ]
    CODE:
    add函数把接受的参数相加,并把和打印出来,注意args前面有一个*
    def add(*args):
            sum = 0
            for i in args:  # 遍历数组
                    sum += i
            print sum

    # 情况1:所有参数使用缺省值
    # 输出结果:abcdef
    func()

    # 情况2:前面的参数使用指定值,后面的参数使用缺省值
    # 输出结果:ABCdef
    func('A', 'B', 'C')

    # 情况3:任意指定哪些参数接受缺省值,哪些参数使用指定值
    # 输出结果:aBcDeF
    func(b = 'B', d = 'D', f = 'F')

  • 使用lambda生成一个新的函数

    [Copy to clipboard] [ - ]
    CODE:
    def generate_multiplier(factor):
            return lambda x: x * factor

    # 生成一个功能为乘以2的函数mul2,输出结果为200,mul2的定义相当于:
    # def mul2(x):
    #         return x * 2
    mul2 = generate_multiplier(2)
    print(mul2(100))

    # 生成一个功能为乘以4的函数mul4,输出结果为400,mul4的定义相当于:
    # def mul4(x):
    #         return x * 4
    mul4 = generate_multiplier(4)
    print(mul4(100))

    # 生成一个功能为乘以8的函数mul8,输出结果为800,mul8的定义相当于:
    # def mul8(x):
    #         return x * 8
    mul8 = generate_multiplier(8)
    print(mul8(100))

6、列表、字典、元组
待续...
7、字符串处理
待续...
8、面向对象编程:封装、继承、虚拟函数、接口、多继承、模板
Python是一种典型的动态类型语言,由于他的动态性:
  • 天生支持虚拟函数、接口、模板等特征,无须引入特定的关键字
  • 在多继承中不存在“菱形继承”引发的问题

下面我们通过举例的方式学习面向对象语言中的各种特性

1、封装

[Copy to clipboard] [ - ]
CODE:
class Person:
        def __init__(self, name):
                self.name = name
        def getName(self):
                return self.name

person = Person('person')
print 'name = %s' % person.getName()

程序输出:
name = person

与C++不同的地方:
  • 类的成员函数的第一个参数是指向这个对象的self引用
  • 在成员函数里,必须通过self引用访问其他的成员变量或者成员函数

    [Copy to clipboard] [ - ]
    CODE:
    class Person:
            def __init__(self, name):
                    self.name = name
                    getName()
            def getName(self):
                    return self.name

    person = Person('person')
    print 'name = %s' % person.getName()

    运行时刻出错,NameError: global name 'getName' is not defined

  • 构造函数的名称为__init__


2、继承

[Copy to clipboard] [ - ]
CODE:
class Chinese(Person):
        def __init__(self, name, company):
                Person.__init__(self, name)
                self.company = company
        def love(self):
                print '%s is Chinese, he love working' % self.name
        def work(self):
                print '%s is working in %s' % (self.name, self.company)

class Japanese(Person):
        def __init__(self, name, interesting):
                Person.__init__(self, name)
                self.interesting = interesting
        def love(self):
                print '%s is Japanese, he love playing' % self.name
        def play(self):
                print '%s is playing %s' % (self.name, self.interesting)

zhangSan = Chinese('Zhang San', 'HuaWei')
zhangSan.love()
zhangSan.work()

sanJing = Japanese('San Jing', 'Basketball')
sanJing.love()
sanJing.play()

程序输出:
Zhang San is Chinese, he love working
Zhang San is working in HuaWei
San Jing is Japanese, he love playing
San Jing is playing Basketball

3、虚拟函数

[Copy to clipboard] [ - ]
CODE:
zhangSan = Chinese('Zhang San', 'Hua Wei')
sanJing = Japanese('San Jing', 'Basketball')

persons = [zhangSan, sanJing]
for person in persons:
        person.love()

程序输出:
Zhang San is Chinese, he love working
San Jing is Japanese, he love playing

这个例子建立了继承于Person的Chinese和Japanese类,Chinese中定义了love和work两个成员函数,Japanese中定义了love和play两个成员函数,注意:
  • Python中没有virtual关键字,默认成员函数都是虚函数,这一点与java类似。
  • 在Chinese和Japanese的父类Person中无须声明两者共同的接口(love函数),这一点与java不同


4、接口

[Copy to clipboard] [ - ]
CODE:
class Cat:
        def __init__(self, name, food):
                self.name = name
                self.food = food
        def love(self):
                print '%s is Cat, he love eating %s' % (self.name, self.food)

def callLove(object):
        object.love()

zhangSan = Chinese('Zhang San', 'HuaWei')
sanJing = Japanese('San Jing', 'Basketball')
mimi = Cat('MIMI', 'fish')
objects = [zhangSan, sanJing, mimi]
for object in objects:
        callLove(object)

程序输出:
Zhang San is Chinese, he love working
San Jing is Japanese, he love playing
MIMI is Cat, he love eating fish

注意:
  • Chinese和Japanese有共同的祖先Person,而Cat和Chinese、Japanese完全不相关
  • 三者都有共同的接口:love函数
  • callLove函数的参数是无类型的,实现以上功能,无须像Java一样要引入interface的概念


5、多继承

[Copy to clipboard] [ - ]
CODE:
class Mix(Chinese, Japanese):
        def __init__(self, cname, jname, company, interesting):
                Chinese.__init__(self, cname, company)
                Japanese.__init__(self, jname, interesting)

mix = Mix('Zhang San', 'San Jing', 'HuaWei', 'Basketball')
mix.love()
mix.work()
mix.play()

程序输出:
San Jing is Chinese, he love working
San Jing is working in HuaWei
San Jing is playing Basketball

  • 这是一个所谓的菱形继承,但是Mix类中只有一份name的拷贝
  • Mix的构造函数中,先调用Chinese的构造函数,把name初始化为Zhang San;随后调用Japanese的构造函数,把name有改为San Jing,因此后面打印出来的名字都是San Jing
  • work是Chinese特有的方法,调用正常
  • play是Japanese特有的方法,调用正常
  • love是Chinese和Japanese共有的方法,这里调用的是Chinese的love方法


6、模板
Python是动态类型的语言,天生支持模板,看两个例子:

函数模板

[Copy to clipboard] [ - ]
CODE:
def min(a, b):
        if (a < b):
                return a
        else:
                return b

print(min(1, 2))
print(min(1.5, 2.5))

类模板

[Copy to clipboard] [ - ]
CODE:
objects = [Person('person'), Cat('mimi')]

Python中内置的高级数据类型有:列表、字典、元组,它们可以存储任意类型的元素,实现容器时无须像C++的stl需要template的支持,这一点与Java类似。

9、面向对象编程:异常处理

捕获除以零的异常

[Copy to clipboard] [ - ]
CODE:
try:
        a = 1
        b = 0
        c = a / b
        print 'Never reach this line'
except ZeroDivisionError:
        print 'Attempt divide by zero'

定义自己的异常

[Copy to clipboard] [ - ]
CODE:
class MyException(Exception):
        def __init__(self, divisor, dividend):
                self.divisor = divisor
                self.dividend = dividend

def divide(divisor, dividend):
        if divisor == 2 * dividend:
                raise MyException(divisor, dividend)
        print '%d / %d = %d' % (divisor, dividend, divisor / dividend)

try:
        divide(9, 3)
        divide(16, 4)
        divide(4, 2)
except MyException, x:
        print 'MyException is raised while execute divide(%d, %d)' % (x.divisor, x.dividend)

finally子句

[Copy to clipboard] [ - ]
CODE:
def openFile():
        try:
                print 'Open File'
                file = open('/etc/passwd')
                c = 1 / 0
        finally:
                print 'Close File'
                file.close()
        print 'Never reach this line'

try:
        openFile()
except:
        print 'Error occured while open file'