简明Python教程笔记

15. 解决问题——编写一个Python脚本

    问题:为所有的重要文件创建备份的程序

    设计中应该明确:
   
    1. 需要备份的文件盒目录由一个列表指定。

    2. 本分应该保存在主备份目录中。

    3. 文件备份成为一个zip文件。

    4. zip存档的名称是当前的日期和时间。

    解决方案:

    方案一:

    #!/usr/bin/python
    #Filename: backup_ver1.py

    import os;
    import time;

    #1. 指定要备份的目录和列表
    # 如果要使用Linux,使用source = ['home/backup', r'home/swaroop/bin'];或者类似这样的
    source = [r'G:\backup', r'G:\backup备份.txt'];
   
    # 2. 备份必须存储在主备份目录
    target_dir = r'G:\backup';
   
    # 3. 文件备份为rar文件
    # 4. rar归档文件的名称是当前的日期和时间
    target = target_dir + time.strftime('%Y%m%d%H%M%S') + '.rar';
   
    # 5. 使用rar命令将文件放入rar归档文件中
    rar_command = "rar a '%s' '%s' "  %(target, ''.join(source));
   
    # Run the backup
    if os.system(rar_command) == 0:
        print 'Successful backup to', target;
    else:
        print 'Backup FAILED';

    注解:
   
    获得日期与时间,使用time.strtime()函数获得。

    %Y会被无世纪的年份代替,%m会被01到12之间十进制月份代替,一次类推。

    使用的压缩命令是winrar a f:\backup\backup f:\backuping\201104111705.rar

    字符串的join方法把source列表 转换为一个字符串

    使用os.system函数运行命令,利用这个函数就行是在系统中运行命令一样,即在shell中运行命令,如果成功,则返回0, 否则返回错误号。

    注:在Python中'\'是转义字符,如果要在字符串中使用'\',则使用'\\'。

    版本二:

    采用一种更加好的文件名机制,使用时间作为文件名,使用当前的日期作为目录名称。这样使得你的备份会以等级结构存储,更加容易管理。并且可以缩短文件的名称长度。

    #!/usr/bin/python
    # -*- coding: cp936 -*-
    #Filename: backup_ver2.py
   
    import os;
    import time;
   
    # 要进行备份的目录和文件放入source中
    source = ['\\backup', '\\backup备份.txt'];
    sourcename = ['backup', 'backup备份.txt'];
   
    # 备份必须存储在主目录中
    target_dir = 'f:\\backup\\';
    source_dir = 'f:\\backuping';
   
    # 文件备份为rar文件
    # 当前的日期是主目录下的子目录
    today = target_dir + time.strftime('%Y%m%d');
   
    # 当前时间是rar归档文件的名字
    now = time.strftime('%H%M%S');
   
    # 如果没有存在,则创建子目录
    if not os.path.exists(today):
        os.mkdir(today);    # 创建目录
   
    print 'Successfully created directory', today;
   
    #备份名称
    i = 0;
    while i < len(source):
        target = today + os.sep + now + sourcename[i] + '.rar';
        print target;
        rar_command = "winrar a %s %s" %(target, source_dir + source[i]);
        if os.system(rar_command) == 0:
            print 'Susccessful backup to', target;
        else:
            print 'Failed to backup file';
        i = i + 1;
    else:
        print 'Backup all file successfully!';
   
    修改的主要部分:使用os.exists函数检验在主备份目录中是否有以当前日期作为名称的目录,如果没有使用os.mkdir函数创建。

    其中的os.sep变量 - 它会根据操作系统给出的目录分隔符,即在Linux下是'\',在windows下是'\\',而在mac下是':'。使用os.sep而非直接使用字符,会使我们的程序具有移植性。

    版本三:

    #!/usr/bin/python
    # -*- coding: cp936 -*-
    #Filename: backup_ver3.py
   
    import os;
    import time;
   
    # 要进行备份的目录和文件放入source中
    source = ['\\backup', '\\backup备份.txt'];
    sourcename = ['backup', 'backup备份.txt'];
   
    # 备份必须存储在主目录中
    target_dir = 'f:\\backup\\';
    source_dir = 'f:\\backuping';
   
    # 文件备份为rar文件
    # 当前的日期是主目录下的子目录
    today = target_dir + time.strftime('%Y%m%d');
   
    # 当前时间是rar归档文件的名字
    now = time.strftime('%H%M%S');
   
    # 为文件名加入注释
        comment = raw_input('Enter a coment -->');
   
    if len(comment) == 0:
        comment = "";
    else:
        comment = comment.replace(' ', '_');
   
    print comment;
   
    # 如果没有存在,则创建子目录
    if not os.path.exists(today):
        os.mkdir(today);    # 创建目录
   
    print 'Successfully created directory', today;
   
    #文件名称   
    i = 0;
    while i < len(source):
        target = today + os.sep + now + sourcename[i] + comment + '.rar';
        print target;
        rar_command = "winrar a %s %s" %(target, source_dir + source[i]);
        if os.system(rar_command) == 0:
            print 'Susccessful backup to', target;
        else:
                print 'Failed to backup file';
        i = i + 1;
    else:
        print 'Backup file successful!';
   
   
    raw_input函数得到用户的输入,然后通过len函数找到输入的长度,以检验是否确实输入了东西。

    将输入的注释中的空格换为_以作为文件名称。


    进一步进行改进:

    * 可以从命令行将要备份的文件传递给程序,使用list类的extend方法将他们加入到source列表中去。

    * 最理想的归档的方法是使用zipfile和tarfile,这两个函数是Python标准库中的方法,使用这两个函数,就不需要使用os.system这个函数了,因为这个函数很容易引发错误。


16. 面向对象编程

    对象可以好似用普通的 属于 对象的变量存储数据。属于一个对象或者是类的变量称为域,对象也可以使用属于类的函数来具有功能。域与方法合称为类的属性。

    域有两种类型—— 属于每个实例/类的对象或者是属于类本身,他们分别称为实例变量和类变量。

    类的方法与普通的函数只有一个区别——它必须有一个额外的第一个参数名称,但是调用的时候不需要调用者为这个参数赋值,Python会自动提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self

    注:虽然可以给这个参数任何名称,但是建议使用self这个名称。使用标准名称,可以让读者迅速识别,一些IDE也有一些支持。
   
    self原理:假如你有一个MyClass类,以及这个类的一个实例MyObject,当调用MyObject.method(arg1, arg2)的时候,这会由Python自动转化为MyClass.method(MyObject, arg1, arg2)。

    1. 简单类的例子
    一个最简单的类的例子:
    #!/usr/bin/python

    #Filename: simplestclass.py

    class Person:
        pass # An empty block

    p = Person();  #一定注意缩进,在Python中缩进就相当于括号的作用
    print p;

    2. 类的方法
    类/对象可以拥有像函数一样的方法,这些方法与函数的区别只是一个额外的self变量。
  
    一个例子:
    #!/usr/bin/python
    #Filename: method.py

    class Person:
        def sayHi(self):
            print 'Hello, how are you?';

    p = Person();
    p.sayHi();      # Also can be written as Person().sayHi();
   
    本例中的self参数必须写入sayHi函数中,但是在执行时不需要给self赋值,系统会自动给它赋值。


    Python的类中,很多方法的名字有特殊的重要意义。
   
    __init__ 方法

   
    该方法在类的一个对象被创建时,马上运行。这个方法用来对你的对象做一些希望的初始化的工作。

    注:改函数名称的开头和结尾都是双下划线。

    #!/usr/bin/python

    # Filename: class_init.py

    class Person:
        def __init__(self, name):
            self.name = name;

        def sayHi( self):
            print 'Hello, my name is ', self.name;

    p = Person('Andy');
    p.sayHi();

       
    本例中给Person类加了一个域 self.name。
   
    其实__init__() 函数就是类的初始化函数,

   

    3. 类的数据

    类的数据其实就是与对象的命名空间绑定的普通变量,这些名称在这些类与对象的前提下有效。

    有两种类型的域: 类的变量和对象的变量,它们根据是类还是对象 拥有这个变量而区分。

    类变量:由一个类的所有对象(实例)共享使用。只有一个类变量的拷贝,当某个对象对类的变量做了改动,
    这个改动会反应到所有其他的实例上。

    对象的变量:由类的每个对象/实例拥有。因此每个对象有自己对这个域的一个拷贝,即它们不是共享的。
    在同一个类的不同的实例中,虽然对象的变量有相同的名称,但是相互不相关。

    #!/usr/bin/python
    #Filename: objvar.py
   
    class Person:
        '''Represents a person.''';
        population = 0;
   
        def __init__(self, name):
            self.name = name;

            print '(Initializing %s)' %self.name;
            # when this person is created, he/she adds to the population
            Person.population += 1;
   
        def __del__(self):
            '''I am dying.'''
            print '%s say bye.' %self.name;
            Person.population -= 1;
   
            if Person.population == 0:
                print 'I am the last one.';
            else:
                print 'There are still %d people left.' %Person.population;

        def sayHi(self):
            '''Greeting by the person.
            Really, that's all it does.'''
       
            print 'Hi, my name is %s.' %self.name;
           
        def howMany(self):
            '''Prints the current population.'''  #文档字符串
            if Person.population == 1:
                print 'I am the only person here.';
            else:
                print 'We have %d persons here.' %Person.population;
   
    Andy = Person('Andy');
    Andy.sayHi();
    Andy.howMany();

    kalam = Person('Abdul Kalam');
    kalam.sayHi();
    kalam.howMany();
   
    Andy.sayHi();
    Andy.howMany();
               
    del Andy;
    del kalam;
   
    population属于Person类,它是一个类的变量,name变量属于对象(使用self赋值),它是对象的变量。

    只能使用self变量来访问同一个对象的变量和方法,被称为属性访问。

    本程序中可以看到docstring对类和方法同样有用。可以在运行时使用

    Person.__doc__和Person.sayHi.__doc__来分别访问类与方法的文档字符串。

   
    如同__init__()方法,__del__()方法也是一个特殊的方法,它是在对象销毁的时候被调用。

    对象销毁,即对象不再被使用,它所占用的内存将返回给系统。
    在代码中可以调用del obj 来显示销毁对象,否则该对象的销毁由系统来做。


    注:数据成员以双下划线为前缀,例如__privatevar,Python的名称管理体系会有效地把它作为私有变量。

 
    惯例:某个变量只想在类或对象中使用,就应该以单下划线前缀,其他的名称都作为公共的,可以被其他的
    类/对象使用。(与双下划线前缀不同)。
   

    4. 继承

    面向对象的编程带来的主要好处之一是代码的重用,实现这一机制可以通过 继承实现。

    继承可以理解为类之间的类型和子类型的关系。

   
    为了记录师生的信息,如果没有继承,则需要写两个类,每一个类都要将一些变量重新写一遍。

    一个比较好的方法是创建一个共同的类称为 SchoolMember,然后让教师和学生的类 继承这个共同的类

    它们都是这个类的子类型,然后为这些子类型添加专有的属性。

    一个子类型在任何需要父类型的场合可以被替代成父类型,即对象可以被视作父类的实例,这种现象成为多态

    那就就有  父类/超类   子类/导出类  区分。


    #!/usr/bin/python

    #Filename: inherit.py

    class SchoolMember:
        '''Represents any school member.'''
        def __init__(self, name, age):
            self.name = name;
            self.age = age;
            print '(Initialized SchoolMember: %s)'%self.name;
   
        def tell(self):
            '''Tell my details.'''
            print 'Name: %s Age:%s' %(self.name, self.age);

    class Teacher(SchoolMember):
        '''Represents a teacher.'''
        def __init__(self, name, age, salary):
            SchoolMember.__init__(self, name, age);
            self.salary = salary;
            print 'Initialized Teacher: %s'%self.name;

        def tell(self):
            SchoolMember.tell(self);
            print 'Salary: %d' %self.salary;
   
    class Student(SchoolMember):
        '''Represents a student.'''
        def __init__(self, name, age, marks):
            SchoolMember.__init__(self, name, age);
            self.marks = marks;
            print 'Initialized Teacher: %s'%self.name;

        def tell(self):
            SchoolMember.tell(self);
            print 'Marks: %d' %self.marks;

    t = Teacher('Mrs. Shrividya', 40, 30000);
    s = Student('Swaroop', 22, 75);

    print ;

    members = [t, s];
    for member in members:
        member.tell();

   
    实现继承class Teacher(SchoolMember): ,基类的__init__()方法要使用self专门调用

    这一点很重要:Python不会自动调用基类的构造函数,需要我们自己专门调用。
  
    在基类构造方法前加基类名称,使用self和其他的参数进行调用。
   
    在子类名后的元组中列举了不止一个类名,那么则是多继承。

   
17. 输入/输出

    程序与用户交互,从用户得到输入,然后打印结果。分别使用raw_input和print方法实现。

    还可以使用str(字符串)类进行输出,可以参考help(str)


    文件

    创建一个file类的对象打开一个文件,分别用file类的read、readline或write方法来读写文件。

    文件操作完毕,调用close方法,关闭文件。

    #!/usr/bin/python
    #Filename: using_file.py

    poem='''\
    Programming is fun
    When the work is done
    if you wanna make your work also fun:
    use Python!
    ''';

    f = file('poem.txt', 'w'); # open for 'w'riting

    f.write(poem); # write text to file

    f.close(); # close the file

    f = file('poem.txt');
    # if no mode is specified, 'r'ead mode is assumed by default

    while True:
        line = f.readline();
        if len(line) == 0: # Zero length indicates EOF
            break;

        print line,       # Notice comma to avoid automatic newline added by Python

    f.close(); # close the file
 
    通过指定希望打开的文件和模式来创建一个file类的实例,

    模式可以为读模式('r')、写模式('w')、追加模式('a'),更多的模式可以参考help(file)文档了解。

    文件使用完毕后,一定调用close方法关闭文件。

    不指定文件模式,则是按照读模式打开。使用readline方法读取一行,这一行包含行尾的换行符。
 
    返回值为空字符串时,表明到达了文件的结尾。

    在print语句上使用逗号可以消除自动换行。

   

    持久地存储对象,Python提供了一个标准的模块,pickle,使用它可以在文件中存储任何Python对象,之后可以把它从文件中完整读取出来。
 
    还有一个类似的模块,成为cPickle,它是使用C语言写的,比pickle模块要快很多。

    #!/usr/bin/python
    #Filename: pickling.py

    import cPickle as p;

    #import pickle as p

    shoplistfile = 'shoplist.data';

    shoplist = ['apple', 'mango', 'carrot'];

    f = file(shoplistfile, 'w');

    p.dump(shoplist, f); # dump the object to a file

    f.close();

    del shoplist;

    f = file(shoplistfile);
    storedlist = p.load(f);

    print storedlist;
  
    import .. as 语法,一种便利的使用方法,以便于可以使用更短的模块名称。他还以简单地通过一行就切换到另外一个模块中(cPickle或者pickle)。

    调用存储器模块的dump函数将对象存储到打开的文件中。通过load函数返回来取得对象。


18. 异常

    程序出现某些异常的状况时候,异常就发生了。最常见的是如果要读取文件时候,文件不存在,或者运行时不小心删除了,再访问就会出现异常。

    错误:如果有错误,源码是无法执行的,并且会打印出错误的地方。

    try ... except

    >>> S = raw_input('Enter something-->');
    Enter something-->

    Traceback (most recent call last):
      File "<pyshell#0>", line 1, in <module>
        S = raw_input('Enter something-->');
    EOFError: EOF when reading a line
   
    EOFError Python引发了一个成为EOFError的错误,这个错误基本上是意味着它发现了一个不期望的文件尾。
    (这个文件尾是由Ctrl-d引起的)

    异常处理:
 
    使用try ... except语句来处理异常。通常将语句放在try-块中,而把我们的错误处理语句放在except-块

    例子:
    #!/usr/bin/python
    #Filename : try_except.py

    import sys;

    try:
        s = raw_input('Enter something -->');
    except EOFError: # catch EOFError
        print '\nWhy did you do an EOF on me?';
        sys.exit(); # exit the program

    except:   # Catch any error
        print '\n Some error/exception occurrd.';
        # here, we are not exiting the program

    print 'Done';

    except从句可以专门处理单一的错误或异常,或者一组包括在圆括号内的错误/异常。如果没有给出错误或
    异常的名称,它会处理所有的错误和异常。对于每一个try从句,至少有一个相关联的except从句。


    如果某个错误或异常没有被处理,默认的Python处理器就会被调用。它会终止程序,并且打印一个消息。

    也可以使用try...catch块关联一个else从句。当没有异常的时候,else从句将被执行。


    引发异常:
  
    使用raise语句引发异常,还需要指明错误/异常的名称或伴随异常触发的异常对象。引发的错误或异常
    应该分别从一个Error或Exception类直接或间接导出类。

    #!/usr/bin/python
    #Filename: raising.py

    class ShortInputException(Exception):
        '''A user-defined exception class.'''

        def __init__(self, length, atleast):
            Exception.__init__(self);

            self.length = length;
            self.atleast = atleast;

    try:
        s = raw_input('Enter something-->');
        if len(s) < 3:
           raise ShortInputException(len(s), 3);
        #Other work can continue as usual here

    except EOFError:
        print '\nWhy did you do an EOF on me?';
    except ShortInputException, x:
        print 'ShortinputExcetion: The input was of length %d, was excepting at least %d' %(x.length, x.atleast);
    else:
        print 'No exception was raised.';

    此处创建了一个自己的异常类型,可以使用预定义的异常/错误。新的异常类型ShortInputException,两个域

    length是给定的输入的长度,atleast则是程序期望的最小的长度。


    使用finally
    #!/usr/bin/python
    #Filename: finally.py

    import time

    try:
        f = file('poem.txt');
        while True:
            line = f.readline();
            if len(line) == 0:
                break;
            time.sleep(2);

            print line;
   
    finally:
        f.close();
        print 'Clean up... closed the file';
   

    使用time.sleep(2)故意让程序休眠2秒,这样可以有时间按下ctrl-c。

    按下ctrl+c后,程序中断,出发KeyboardInterrupt异常被触发,程序退出,但是退出之前,finally从句依然要被执行。

 

19. Python的标准库

    sys模块

    sys.argv的用法
   
    #!/usr/bin/python
    #Filename: cat.py
   
    import sys
    def readfile(filename):
        '''Print a file to standard output'''
        f = file(filename);
        while True:
            line = f.readline();
            if len(line) == 0:
                break;
            print line;
        f.close(); # don't close the file before finished.
   
    #script start from here
    if len(sys.argv) < 2:
        print 'No action specified.'
        sys.exit();
   
    if sys.argv[1].startswith('--'):
        option = sys.argv[1][2:];
   
        #fetch sys.argv[1],but without the first two characters
        if option == 'version':
            print 'Version 1.2'
        elif option == 'help':
            print '''\
        This program prints files to standard output.
        Any number of files can be specified.
        Options include:
        --version: Prints the version number
        --help:Display this help'''
        else:
        print 'Unknow option';
       
        sys.exit();
   
    else:
        for filename in sys.argv[1:]:
            readfile(filename);
   
    sys.argv列表中至少有一个项目,sys.argv[0]中保存的是当前运行的程序的名称。
    对指定的参数,是--version 或 --help将打印相应的一些信息

    使用sys.exit()方法退出程序

    更多sys内容:

    sys.version字符串提供的是安装的Python的版本信息。sys.version_info元组则提供一个更简单的版本信息。如下:

    >>> import sys;
    >>> sys.version
        '2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)]'
    >>> sys.version_info
        sys.version_info(major=2, minor=7, micro=2, releaselevel='final', serial=0)


    sys的标准输入输出项目:

    sys.stdin  sys.stdout  sys.stderr

    对应于标准输入输出,与标准错误流


    OS模块

    os.sep 取代操作系统的特定的路径分隔符。

    os.name 字符串显示正在使用的平台,不如Window 为nt Linux/unix为 posix。

    os.getcwd()获得当前工作目录,即当前Python脚本的工作的目录路径

    os.getenv() 和 os.putenv():放别用来读取和设置环境变量

    os.listdir():返回指定目录下的所有的文件和目录名

    os.remove(): 删除一个文件

    os.system(): 用来运行shell命令

    os.linesep(): 给出当前平台使用的行终止符,例如windows使用'\r\n', Linux使用'\n'等

    os.path.split() 返回一个路径的目录名和文件名

    os.path.isfile() 和 os.path.isdir() : 分别判断是否是文件和目录

    os.path.existe() 判断目录或文件是否存在。


20. 更多的Python的内容

    特殊的方法:

    __init__(self, ...): 这个方法在新建对象恰好要被返回使用之前调用

    __del__(self): 恰好在对象被删除之前调用

    __str__(self): 在对对象使用print语句或是使用str()的时候调用

    __It__(self, other): 当使用小于 运算符(<)的时候调用。类似地,对于所有的运算符(+, > 等等)都有特殊方法

    __getitem__(self, key): 在使用x[key]索引操作符的时候调用

    __len__(self): 对对象使用内建的len()函数时调用


    将元组和字典作为函数参数:

    #!/usr/bin/python
    # Filename: tupleAsPara.py
   
    def powersum(power, *args):
        total = 0;
        for i in args:
            total += pow(i, power);
   
        return total;
   
    print powersum(2, 3, 4);
   
    print powersum(2, 10);

    由于args变量前有*前缀,所有多余的函数参数都会作为一个元组存储在args中。

    如果使用**前缀,多余的参数则会被作为一个字典的键值对,存入args。


    exec和eval语句:

    exec语句用来执行存储在字符串或文件中的python语句。

    可以生成一个Python代码的字符串,然后使用exec语句执行这些语句。

    例如:

    exec 'print "hello world"';

    eval语句用来计算存储在字符串中有效的Python表达式,例如:

    eval('2*3');

   
    assert语句:

    assert语句用来声明某个条件是真的。如果条件为假,则会引发错误,AssertionError错误。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值