• 本文首发于http://www.52aite.cn博客,没有知乎,没有微信公众号,只是蹭一波python跳一跳的热度 python辅助作者github账号为:wangshub。 作者的知乎专栏为:https://zhuanlan.zhihu.com/p/3

    为了让各位小伙伴都能使用黑科技,于是做了一个超详细教程。从Python的安装开始,手把手教你一步一步配置好环境直到成功运行。

    本文首发于http://www.52aite.cn博客,没有知乎,没有微信公众号,只是蹭一波python跳一跳的热度

    python辅助作者github账号为:wangshub。

    作者的知乎专栏为:https://zhuanlan.zhihu.com/p/32452473

    下面进入正文。

    本文适用对象为WIN10系统,安卓用户。目的在于让丝毫没有接触过Python的小伙伴都能成功运行,如果你恰好是这样的对象,那么跟着我开始操作。我会把我自己的每一步都写下来。

    准备工具:

    Windows 10; 
    一个安卓真机 
    python 3 
    adb驱动 
    依赖安装包(这个在源码中已经列出,下面会详细说明)

    0x01:Python下载

    进入Python官方网站,将Python下载下来。在官网点击Download,选择Windows,进入下载页面,根据自己的系统下载对应的Python安装程序,32位的下载X86,64位的下载X86-64。如图所示:

    Python的下载与安装

    将Python下载到电脑之后点击安装,在安装的时候有一个步骤非常重要,就是自动配置环境变量,这里一定要勾选上。如图所示:

    Python自动配置环境变量

    这一步勾选上后,就一直点next直到Python完成安装,Python完成安装后打开CMD控制台,输入命令Python,出现如下界面,即为安装成功。如图所示:

    查看Python是否安装成功

    0x02:pip安装

    pip类似CentOS里面的yum,用来安装Python包非常方便,因为运行这个跳一跳辅助将会用到很多的依赖包,这些依赖包将要用到pip下载,所以我们首先把pip装好。

    事实上在新下载的Python中已经有pip功能,这一步好像写得有点多余了,以前记得是要重新下载pip的,既然现在的最新版Python可以直接使用pip功能,我们可以在CMD控制台直接输入pip,看是否有以下界面显示,出现如下界面即可正常使用pip功能。

    使用pip命令

    0x03:adb驱动安装

    adb驱动下载地址:https://adb.clockworkmod.com/

    安装时候选择一个容易记住的路径,这个很重要,因为adb驱动没有自动配置环境变量,所以实验时候将adb安装在一个非常容易记住的路径,这里以E:\adb为例。如图:

    adb驱动安装

    安装完成后我们在CMD控制台输入adb是没有反应的,因为我们还没有配置好adb的环境变量,我们可以右键点击我的电脑,选择属性,点击高级系统设置,在高级中点击环境变量。

    环境变量配置

    进入环境变量配置页面之后,在系统变量中找到Path,点击Path再点击编辑,然后将刚才安装adb的路径复制,这里我们是以E:\adb为例的,所以我们将这个路径加入进环境变量中,点击保存。这时候我们再次打开CMD控制台,输入adb,出现如下界面,即为配置成功。如图:

    adb命令

    0x04:源码拷贝

    到这一步,我们要将源码下载到本地电脑里。

    github地址:https://github.com/wangshub/wechat_jump_game

    进入github后,点击clone or downloads,把源码下载到本地。如图所示:

    github下载项目源码

    0x05:安装依赖安装包

    跳一跳微信辅助的最终运行需要很多的Python模块,作者已经将这些所需要的模块都写在了源码中的requirements.txt中,所以我们执行命令 pip install -r requirements.txt,即可将这些必须的模块下载下来,模块包括有matplotlib,numpy等。

    如图,我们使用CD命令,切换到源码的下载目录,再执行命令pip install -r requirements.txt

    下载相关依赖包

    一定要记得切换目录后再执行命令。

    0x06:手机与电脑连接

    将安卓手机用USB与电脑相连接,在安卓手机上打开开发者模式,并开启USB调试模式,每种安卓手机开启的方法都不一样,这里需要小伙伴自己查询自己型号的手机如何开启开发者模式,以OPPO A57手机为例,在设置中找到手机版本号,连续点击5次即可开启开发者模式。

    如果以上操作没有任何错误,那么在CMD控制台,执行命令 adb devices可显示当前手机连接的端口号。

    0x07:运行跳一跳

    在以上步骤都没有任何错误的情况下,打开微信,开启跳一跳小游戏,进入游戏主页面,然后再打开CMD控制台,使用CD命令切换目录,切换到跳一跳辅助的源码目录下,执行命令wechat_jump_auto.py。

    这时候,你会惊奇的发现,你的手机上那个小人已经开始成功的开始自动跳跃了,不过一开始可能分数不高,这就需要自己耐心的慢慢调节参数了,以上几个步骤都坚持下来的小伙伴们,想必调节参数也是会非常有耐心的。

    参数调节请打开源码目录下的config文件夹,里面有适配各种屏幕和机型的文件夹,根据自己的分辨率或机型,点击进入相应文件夹,打开里面的config.json文件,修改参数即可。建议修改前最好备份一份。

    晒高分,秀战绩。小伙伴们都high起来吧。

    微信跳一跳高分秘籍

    展开全文
  • Python程序: print("hello world") 如何退出Python的解释器提示符: ​ 在Linux或OS X的shell程序中,可以通过按下[ctrl+d]或输入exit()。 ​ 在windows命令提示符中,可以按下[ctrl+z]组合键,然后敲击...

    基本知识

    第一个Python程序:

    print("hello world")
    

    如何退出Python的解释器提示符:

    ​ 在Linux或OS X的shell程序中,可以通过按下[ctrl+d]或输入exit()。

    ​ 在windows命令提示符中,可以按下[ctrl+z]组合键,然后敲击[center]键来退出。

    注意:

    Python 是区分大小写的,如 print 和 Print 是不同的——注意前者的 p 是小写的,而后者的 P 是大写的。此外,你需要确保每一行的第一个字符前面都没有任何空格或制表格。

    注释

    ​ 注释 是任何存在于 # 号右侧的文字,其主要用作写给程序读者看的笔记。

    ​ 举个例子:

    print('hello world') #注意到 print 是一个函数
    

    ​ 或者:

    # 注意到 print 是一个函数
    print('hello world')
    

    字面常量

    ​ 可以直接表示其字面意思的量,例如5、1.23这样的数字或字符串文本。

    数字

    ​ 数字主要分为两种类型——整数(Integers)与浮点数(Floats)。

    ​ 针对有经验的程序员的提示
    ​ 没有单独的 long 类型。 int 类型可以指任何大小的整数。

    字符串

    ​ 一串字符串(String)是 字符(Characters) 的 序列(Sequence)。基本上,字符串就是一串词汇。

    ​ 单引号和双引号的作用差不多,都是指定字符串:

    ​ '我是一个字符串’和“我是一个字符串”的效果一样。

    ​ 三引号,主要用于多行字符串,在三引号中可以任意使用单引号和双引号。例如:

    '''这是一段多行字符串。这是它的第一行。
    This is the second line.
    "What's your name?," I asked.
    He said "Bond, James Bond."
    '''
    

    字符串是不可变的。

    ​ format可以使用内容填充字符串中的占位符(格式)。

    ​ print输出字符串时,会在末尾自动加上换行符“\n”,可以使用end参数替换掉换行符。例如:

    print('a',end='')
    print('b',end='')
    

    ​ 输出结果如下:

    ab
    

    转义序列

    ​ 对于有特殊含义的字符出现在字符串中,需要使用转义序列""来进行转义,例如’What’s your name’在python中会报错,你需要对其中的但引号进行转义,‘What’s your name’。

    ​ 最重要的转义序列:\n代表换行,\t代表制表符

    ​ 在一个字符串中,一个放置在末尾的反斜杠表示字符串将在下一行继续,但不会添加新的一行。来看看例子:

    "This is the first sentence. \
    This is the second sentence."
    

    相当于:

    "This is the first sentence. This is the second sentence."
    

    原始字符串

    在字符串前面使用r或R可以表示这个字符串没有经过任何处理,也就是原样输出。

    r"Newlines are indicated by \n"
    

    在使用正则表达式时,应该全程使用原样字符串。举例说明的话,反向引用可以通过 ‘\1’ 或 r’\1’ 来实现。

    变量

    ​ 可以存储任何信息,并且也能够操作它们。

    标识符命名

    ​ 就是给某些东西一个名称。标识符命名规则和C语言、Java的一样,标识符中只能有字母、数字、下划线,并且开头只能是字母或数字。

    数据类型

    ​ 变量可以将各种形式的值保存为不同的数据类型(Data Type)。基本的类型是我们已经讨论过的数字与字符串。

    对象

    ​ Python将程序中的任何内容统称为对象(Object)。

    ​ 针对面向对象编程语言用户的提示:
    ​ Python 是强(Strongly)面向对象的,因为所有的一切都是对象, 包括数字、字符串与
    ​ 函数。

    ​ 针对静态编程语言程序员的提示:变量只需被赋予某一值。不需要声明或定义数据类型。

    物理行与逻辑行

    ​ 在编辑器中看到的一行代码就是物理行,Python所读到的一个语句就是一个逻辑行。

    ​ Python隐藏的期望是在一行中只写一个语句,也就是尽量不要使用分号。

    ​ 如果一行代码实在是太长了,可以使用反斜杠""将其拆分成多个物理行,这被称作显式行连接。

    ​ 例如:

    i=\
    5
    #等价于
    i=5
    

    ​ 在某些情况下,会存在一个隐含的假设,允许你不使用反斜杠。这一情况即逻辑行以括号开始,它可以是方括号或花括号,但不能是右括号。

    缩进

    ​ 每个语句 前面的空白区就是缩进,空白区可以确定逻辑行的缩进级别,而缩进级别又可以用于确定语句的分组。

    ​ 有一件事你需要记住:错误的缩进可能会导致错误。

    ​ Python官方的建议是使用四个空格来缩进。

    运算符与表达式

    ​ 表达式可以拆分成运算符(Operators)与操作数(Operands)。

    ​ 各个操作符的详细信息参考《简明Python教程》的p45-46的运算符的速览。

    ​ 基本的操作符都和Java的一样,需要注意的是逻辑非用“not”、逻辑与用“and”、逻辑或用“or”。

    数值运算与赋值的快捷方式

    ​ 其实就是Python的数值运算支持乘赋“*=”等快捷操作。例如:

    a=2
    a=a*3
    #等价于
    a=2
    a *= 3
    

    求值顺序

    ​ Python中对于运算符的优先级也是有规定的,《简明Python教程》中有说明,在P47页,也可以参考Python的手册。最好是使用圆括号对运算符和表达式进行分组。

    控制流

    ​ 在Python中有三种控制流语句——if、for和while。

    if 语句

    示例:

    number = 23
    guess = int(input('Enter an integer : '))
    
    if guess == number : # 我们借助这个冒号向Python指定接下来会有一块语句在后头
        # 新块从这里开始
        print('Congratulations, you guessed it.')
        print('(but you do not win any prizes!)')
    elif guess < number :
        # 另一代码块
        print('No, it is a little higher than that ')
        # 你可以在此做任何你希望在改代码块内进行的事情
    else :
        print('No, it is a little lower than that')
        # 你必须通过猜测一个大于(>)设置数的数字来到达这里。
    
    print('Done')
    # 这最后一句话将在 if 语句执行完毕后执行
    

    输出:

    $ python if.py
    Enter an integer : 50
    No, it is a little lower than that
    Done
    $ python if.py
    Enter an integer : 22
    No, it is a little higher than that
    Done
    $ python if.py
    Enter an integer : 23
    Congratulations, you guessed it.
    (but you do not win any prizes!)
    Done
    

    针对 C/C++ 程序员的提示
    Python 中不存在 switch 语句。你可以通过使用 if…elif…else 语句来实现同样的事情(在某些情况下,使用一部字典能够更快速地完成)。

    while 语句

    ​ while语句是循环语句的一种。while语句同样可以拥有else子句作为可选项。

    number = 23
    running = True
    
    while running :
        guess = int(input('Enter an integer : '))
    
        if guess == number :
            print('Congratulations, you guessed it. ')
            # 这将导致while循环终止
            running = False
        elif guess < number :
            print('No, it is a little higher than that. ')
        else :
            print('No, it is a little lower than that. ')
    else : # 用冒号告诉Python下面有语句块
        print('The while loop is over. ')
        # 在这里你可以做你想做的任何事情
    
    print('Done')
    

    输出:

    $ python while.py
    Enter an integer : 50
    No, it is a little lower than that.
    Enter an integer : 22
    No, it is a little higher than that.
    Enter an integer : 23
    Congratulations, you guessed it.
    The while loop is over.
    Done
    

    ​ 如果 while 循环中存在一个 else 代码块,它将总是被执行,除非你通过 break 语句来中断这一循环。

    针对 C/C++ 程序员的提示
    你可以在 while 循环中使用 else 从句。

    for 循环

    ​ for…in 语句是另一种循环语句,其特点是会在一系列对象上进行迭代(Iterates),意即它会遍历序列中的每一个项目。

    案例:

    for i in range(1, 5) :
        print(i)
    else:
        print('The for loop is over')
    

    输出:

    $ python for.py
    1
    2
    3
    4
    The for loop is over
    

    ​ 要记住, else 部分是可选的。当循环中包含他时,它总会在 for 循环结束后开始执行,除非程序遇到了 break 语句。

    break 语句

    ​ break语句用以中断循环语句,即使循环条件没有变成False,也可以被终止。

    ​ 需要注意的是,如果你中断了一个For或while循环,任何相应循环中的else块都将不会被执行。

    示例:

    while True :
        s = input('Enter something : ')
        if s == 'quit' : #zhg: 注意字符串判断相等的方式
            break
        print('Length of the string is', len(s))
    print('Done')
    

    输出:

    $ python break.py
    Enter something : Programming is fun
    Length of the string is 18
    Enter something : When the work is done
    Length of the string is 21
    Enter something : if you wanna make your work also fun:
    Length of the string is 37
    Enter something : use Python!
    Length of the string is 11
    Enter something : quit
    Done
    

    ​ 记住, break 语句同样可以适用于 for 循环。

    Continue语句

    ​ continue 语句用以告诉 Python 跳过当前循环块中的剩余语句,并继续该循环的下一次迭代。

    示例:

    while True :
        s = input('Enter something : ')
        if s == 'quit' :
            break
        if len(s) < 3 :
            print('Too small')
            continue
        print('Input is of sufficient length')
        # 自此处起继续进行其它任何处理
    

    输出:

    $ python continue.py
    Enter something : a
    Too small
    Enter something : 12
    Too small
    Enter something : abc
    Input is of sufficient length
    Enter something : quit
    

    ​ 要注意 continue 语句同样能用于 for 循环。

    函数

    ​ 函数(Functions)是指可重复使用的程序片段。

    ​ 函数可以通过关键字 def 来定义。这一关键字后跟一个函数的标识符名称,再跟一对圆括号,其中可以包括一些变量的名称,再以冒号结尾,结束这一行。随后而来的语句块是函数的一部分。下面的案例将会展示出这其实非常简单:

    def say_hello() :
        # 该块属于这一函数
        print('hello world')
    # 函数结束
    
    say_hello() # 调用函数
    say_hello() # 再次调用函数
    

    输出:

    $ python function1.py
    hello world
    hello world
    

    函数参数

    ​ 函数的参数就是定义在那个圆括号中变量,通过它们可以向函数传递信息。

    ​ 在定义函数时给定的名称称作“形参”(Parameters),在调用函数时你所提供给函数的值称作“实参”(Arguments)。
    ​ 案例:

    def print_max(a, b) :
        if a > b :
            print(a, 'is maximum')
        elif a == b :
            print(a, 'is equal to', b)
        else :
            print(b, 'is maximum')
    
    #直接传递字面值
    print_max(3,4)
    
    x=5
    y=7
    
    # 以参数的形式传递变量
    print_max(x, y)
    

    输出:

    $ python function_param.py
    4 is maximum
    7 is maximum
    

    局部变量

    ​ 在函数定义中声明的变量就是局部变量,它们不会以任何形式与函数外的同名变量发生联系。

    ​ 所有变量的作用域是它们被定义的块,从定义它们的名字的定义点开始。

    ​ 示例:

    x = 50
    
    def func(x) :
        print('x is', x)
        x = 2
        print('changed local x to', x)
    
    func(x)
    print('x is still', x)
    

    输出:

    $ python function_local.py
    x is 50
    Changed local x to 2
    x is still 50
    

    zhg: python的函数也是遵从值传递规则,即传递给函数参数的是值,而不是地址。

    global 语句

    ​ 使用global语句可以使用并更改函数之外的变量的值。

    ​ 案例:

    x = 50
    
    def func() :
        global x
    
        print('x is', x)
        x = 2
        print('changed global x to', x)
    
    func()
    print('value of x is', x)
    

    输出:

    $ python function_global.py
    x is 50
    Changed global x to 2
    Value of x is 2
    

    ​ global 语句用以声明 x 是一个全局变量——因此,当我们在函数中为 x 进行赋值时,这一改动将影响到我们在主代码块中使用的 x 的值。

    ​ 你可以在同一句 global 语句中指定不止一个的全局变量,例如 global x, y, z 。

    默认参数值

    ​ 你可以通过在函数定义时附加一个赋值运算符( = )来为参数指定默认参数值。

    ​ 默认参数值应该是常量,即是不可变的。

    ​ 示例:

    def say(message, times=1):
        print(message * times)
    
    say('Hello')
    say('World', 5)
    

    输出:

    $ python function_default.py
    Hello
    WorldWorldWorldWorldWorld
    

    注意
    只有那些位于参数列表末尾的参数才能被赋予默认参数值,意即在函数的参数列表中拥
    有默认参数值的参数不能位于没有默认参数值的参数之前。
    这是因为值是按参数所处的位置依次分配的。举例来说, def func(a, b=5) 是有效的,
    但 def func(a=5, b) 是无效的。

    关键字参数

    ​ 可以通过命名的防止给制定参数赋值。

    ​ 示例:

    def func(a, b=5, c=10):
        print('a is', a, 'and b is', b, 'and c is', c)
    
    func(3, 7)
    func(25, c=24)
    func(c=50, a=100)
    

    ​ 输出:

    $ python function_keyword.py
    a is 3 and b is 7 and c is 10
    a is 25 and b is 5 and c is 24
    a is 100 and b is 5 and c is 50
    

    可变参数

    ​ 可以通过星号来实现任意数量的变量

    ​ 示例:

    def total(a=5, *numbers, **phonebook):
        print('a', a)
    
        #遍历元组中的所有项目
        for single_item in numbers :
            print('single_item', single_item)
    
        #遍历字典中的所有项目
        for first_part, second_part in phonebook.items() :
            print(first_part, second_part)
    
    print(total(10, 1, 2, 3, Jack=1123, John=2231, Inge=1560))
    

    ​ 输出:

    $ python function_varargs.py
    a 10
    single_item 1
    single_item 2
    single_item 3
    Inge 1560
    John 2231
    Jack 1123
    None
    

    ​ 当我们声明一个诸如 *param 的星号参数时,从此处开始直到结束的所有位置参数(Positional Arguments)都将被收集并汇集成一个称为“param”的元组(Tuple)。

    ​ 类似地,当我们声明一个诸如 **param 的双星号参数时,从此处开始直至结束的所有关键字参数都将被收集并汇集成一个名为 param 的字典(Dictionary)。

    return 语句

    ​ return语句用于在函数中返回,我们可以选择从函数中返回一个值。

    ​ 示例:

    def maximum(x, y):
        if x > y :
            return x
        elif x == y :
            return 'The numbers are equal'
        else :
            return y
    
    print(maximum(2, 3))
    

    ​ 输出:

    $ python function_return.py
    3
    

    ​ 如果return语句没有搭配任何一个值,则代表返回None。None在Python中是一个特殊的类型,代表着虚无。

    ​ 每一个函数都在其末尾隐含了一句 return None ,除非你写了你自己的 return 语句。你可以运行 print(some_function()) ,其中 some_function 函数不使用 return 语句,就像这样:

    def some_function():
    pass
    

    ​ Python 中的 pass 语句用于指示一个没有内容的语句块。

    提示:有一个名为 max 的内置函数已经实现了“找到最大数”这一功能,所以尽可能地使
    用这一内置函数。

    DocStrings

    ​ 文档字符串就是对函数的一个说明,其实和Java的类似,就是位置和规范不同。

    ​ 示例:

    def print_max(x, y) :
        '''打印两个数值中的最大数
    
        这两个数都应该是整数'''
        # 如果可能,将其转换成整数类型
        x = int(x)
        y = int(y)
    
        if x > y :
            print(x, 'is maximum')
        else :
            print(y, 'is maximum')
    
    print_max(3, 5)
    print(print_max.__doc__)
    

    ​ 输出:

    $ python function_docstring.py
    5 is maximum
    打印两个数值中的最大数。
    
    	这两个数都应该是整数
    

    ​ 函数的第一行逻辑行中的字符串是该函数的 文档字符串(DocString)。

    ​ 该文档字符串所约定的是一串多行字符串,其中第一行以某一大写字母开始,以句号结束。第二行为空行,后跟的第三行开始是任何详细的解释说明。在此强烈建议你在你所有重要功能的所有文档字符串中都遵循这一约定。

    ​ 我们可以通过使用函数的 doc (注意其中的双下划綫)属性(属于函数的名称)来获取函数 print_max 的文档字符串属性。Python将所有东西都视为一个对象,其中包括函数。

    ​ help()函数所做的便是获取函数的 doc 属性并以一种整洁的方式将其呈现给你。

    ​ Python发行版中附带的pydoc 命令与 help() 使用文档字符串的方式类似。

    模块

    ​ 模块就是在不同程序间复用代码的手段。

    ​ 编写模块有很多种方法,其中最简单的一种便是创建一个包含函数与变量、以 .py 为后缀的文件。
    ​ 另一种方法是使用撰写 Python 解释器本身的本地语言来编写模块。

    ​ 一个模块可以被其它程序导入并运用其功能。

    ​ 案例:

    import sys
    
    print('The command line arguments are:')
    for i in sys.argv:
        print(i)
    
    print('\n\nThe PYTHONPATH is', sys.path, '\n')
    

    ​ 输出:

    $ python module_using_sys.py we are arguments
    The command line arguments are:
    module_using_sys.py
    we
    are
    arguments
    
    The PYTHONPATH is ['/tmp/py',
    # many entries here, not shown here
    '/Library/Python/2.7/site-packages',
    '/usr/local/lib/python2.7/site-packages']
    

    需要注意的是,运行的脚本名称在 sys.argv 的列表中总会位列第一。

    按字节码编译的 .pyc 文件

    ​ 可以将Python文件按字节编译成中间文件,这样有利于模块的加载速度。

    from…import语句

    ​ from…import语句可以避免每次使用argv时都要输入"sys.",即使用from sys import argv 语句来实现这一点。

    ​ 示例:

    from math import sqrt
    print("Square root of 16 is", sqrt(16))
    

    模块的__name__

    ​ 每个模块都有一个名称,可以通过模块的名称来确定它是独立运行的还是被导入进来的,这可以通过使用模块的__name__ 属性来实现。。

    ​ 案例:

    if __name__ == '__main__' :
        print('This program is being run by itself')
    else:
        print('I am being imported from another module')
    

    ​ 输出:

    $ python module_using_name.py
    This program is being run by itself
    $ python
    >>> import module_using_name
    I am being imported from another module
    >>>
    

    ​ 每一个 Python 模块都定义了它的 name 属性。如果它与 main 属性相同则代表这一模块是由用户独立运行的。

    编写你自己的模块

    ​ 每一个 Python 程序同时也是一个模块。你只需要保证它以 .py 为扩展名即可。

    ​ 案例:

    def say_hi():
        print('Hi, this is mymodule speaking.')
    
    
    __version__ = '0.1'
    

    ​ 注意:自己定义的模块要放在要导入该模块的程序的所在目录,或者在sys.path所列出的某个目录下。

    ​ 另一个模块:

    import mymodule
    
    mymodule.say_hi()
    print('Version', mymodule.__version__)
    

    ​ 输出:

    $ python mymodule_demo.py
    Hi, this is mymodule speaking.
    Version 0.1
    

    ​ 下面是一个使用 from…import 语法的范本:

    from mymodule import say_hi, __version__
    
    say_hi()
    print('Version', __version__)
    

    ​ 你还可以使用:

    from mymodule import *
    

    ​ 这将导入诸如 say_hi 等所有公共名称,但不会导入 __version__ 名称,因为后者以双下划线开头。

    ​ 警告:尽量不要使用from…import形式,容易引起变量名冲突。

    dir 函数

    ​ 内置的 dir() 函数能够返回由对象所定义的名称列表。

    ​ 该函数接受参数。 如果参数是模块名称,函数将返回这一指定模块的名称列表。 如果没有提供参数,函数将返回当前模块的名称列表。

    案例:

    $ python
    >>> import sys
    # 给出 sys 模块中的属性名称
    >>> dir(sys)
    ['__displayhook__', '__doc__',
    'argv', 'builtin_module_names',
    'version', 'version_info']
    # 此处只展示部分条目
    # 给出当前模块的属性名称
    >>> dir()
    ['__builtins__', '__doc__',
    '__name__', '__package__','sys']
    # 创建一个新的变量 'a'
    >>> a = 5
    >>> dir()
    ['__builtins__', '__doc__', '__name__', '__package__', 'a']
    # 删除或移除一个名称
    >>> del a
    >>> dir()
    ['__builtins__', '__doc__', '__name__','__package__']
    

    ​ 关于 del 的一个小小提示——这一语句用于删除一个变量或名称,当这一语句运行后,在本例中即 del a ,你便不再能访问变量 a ——它将如同从未存在过一般。

    ​ 包是指一个包含模块与一个特殊的 __init__.py 文件的文件夹,后者向 Python 表明这一文件夹是特别的,因为其包含了 Python 模块。

    ​ 让我们这样设想:你想创建一个名为“world”的包,其中还包含着 “asia”、“africa”等其它子包,同时这些子包都包含了诸如“india”、 “madagascar”等模块。

    ​ 下面是你会构建出的文件夹的结构:

    - <some folder present in the sys.path>/
    	- world/
    		- __init__.py
    		- asia/
    			- __init__.py
    			- india/
    				- __init__.py
    				- foo.py
    		- africa/
    			- __init__.py
    			- madagascar/
    				- __init__.py
    				- bar.py
    

    ​ 包是一种能够方便地分层组织模块的方式。你将在 标准库 中看到许多有关于此的实例。

    总结

    ​ 如同函数是程序中的可重用部分那般,模块是一种可重用的程序。包是用以组织模块的另一种层次结构。Python 所附带的标准库就是这样一组有关包与模块的例子。

    数据结构

    ​ 数据结构是用来存储一系列相关数据的集合。

    ​ Python 中有四种内置的数据结构——列表(List)、元组(Tuple)、字典(Dictionary)和集合(Set)。

    列表

    ​ 列表 是一种用于保存一系列有序项目的集合。项目的列表应该用方括号括起来,这样 Python 才能理解到你正在指定一张列表。

    ​ 列表对应的类型是list

    ​ 示例:

    # This is my shopping list
    shoplist = ['apple', 'mango', 'carrot', 'banana']
    
    print('I have', len(shoplist), 'item to purchase.')
    
    print('These items are:', end=' ')
    for item in shoplist :
        print(item, end=' ')
    
    print('\nI also have to buy rice.')
    shoplist.append('rice')
    print('My shopping list is now', shoplist)
    
    print('I will sort my list now')
    shoplist.sort()
    print('Sorted shopping list is', shoplist)
    
    print('The first item I will buy is', shoplist[0])
    olditem = shoplist[0]
    del shoplist[0]
    print('I bought the', olditem)
    print('My shopping list is now', shoplist)
    

    ​ 输出:

    $ python ds_using_list.py
    I have 4 items to purchase.
    These items are: apple mango carrot banana
    I also have to buy rice.
    My shopping list is now ['apple', 'mango', 'carrot', 'banana', 'rice']
    I will sort my list now
    Sorted shopping list is ['apple', 'banana', 'carrot', 'mango', 'rice']
    The first item I will buy is apple
    I bought the apple
    My shopping list is now ['banana', 'carrot', 'mango', 'rice']
    

    元组

    ​ 元组(Tuple)用于将多个对象保存到一起。元组的一大特征类似于字符串,它们是不可变的,也就是说,你不能编辑或更改元组。

    ​ 元组对应的类型是tuple

    ​ 案例:

    # 我会推荐你总是使用括号
    # 来指明元组的开始与结束
    # 尽管括号是一个可选选项。
    # 明了胜过晦涩,显式优于隐式。
    zoo = ('python', 'elephant', 'penguin')
    print('Number of animals in the zoo is', len(zoo))
    
    new_zoo = 'monkey', 'camel', zoo
    print('Number of cages in the new zoo is', len(new_zoo))
    print('All animals in new zoo are', new_zoo)
    print('Animals brought from old zoo are', new_zoo[2])
    print('Last animal brought from old zoo is', new_zoo[2][2])
    print('Number of animals in the new zoo is',
          len(new_zoo)-1+len(new_zoo[2]))
    
    

    ​ 输出:

    $ python ds_using_tuple.py
    Number of animals in the zoo is 3
    Number of cages in the new zoo is 3
    All animals in new zoo are ('monkey', 'camel', ('python', 'elephant', 'penguin'))
    Animals brought from old zoo are ('python', 'elephant', 'penguin')
    Last animal brought from old zoo is penguin
    Number of animals in the new zoo is 5
    

    包含 0 或 1 个项目的元组
    一个空的元组由一对圆括号构成,就像 myempty = () 这样。然而,一个只拥有一个项目的元组并不像这样简单。你必须在第一个(也是唯一一个)项目的后面加上一个逗号来指定它,如此一来 Python 才可以识别出在这个表达式想表达的究竟是一个元组还是只是一个被括号所环绕的对象,也就是说,如果你想指定一个包含项目 2 的元组,你必须指定 singleton = (2, ) 。

    字典

    ​ 字典其实就是一个映射。在字典中键不能重复,并且键必须是不可变的对象,而对应的值可以是可变的或不可变的。

    ​ 另外需要记住,字典中的成对的键—值配对不会以任何方式进行排序。

    ​ 下面使用的字典是属于dict类下的实例或对象。

    # “ab”是地址(Address)簿(Book)的缩写
    
    ab = {
        'Swaroop':'swaroop@swaroopch.com',
        'Larry' : 'larry@qq.com',
        'Matsumoto':'matz@163.com',
        'Spammer':'spammer@hotmail.com'
    }
    
    print("Swaroop's address is", ab['Swaroop'])
    
    # 删除一对键值—值配对
    del ab['Spammer']
    
    print('\nThere are {} contacts in the address-book\n'.format(len(ab)))
    
    for name, address in ab.items() :
        print('Contact {} at {} '.format(name, address))
    
    # 添加一堆键——值配对
    ab['Guido']='guido@python.org'
    
    if 'Guido' in ab :
        print("\nGuido's address is", ab['Guido'])
    

    ​ 输出:

    $ python ds_using_dict.py
    Swaroop's address is swaroop@swaroopch.com
    
    There are 3 contacts in the address-book
    
    Contact Swaroop at swaroop@swaroopch.com
    Contact Matsumoto at matz@ruby-lang.org
    Contact Larry at larry@wall.org
    
    Guido's address is guido@python.org
    

    序列

    ​ 序列的主要功能就是判断是否存在和索引操作。

    ​ 列表、元组和字符串都是序列,它们都拥有切片操作。切片操作可以获取序列中的一部分。

    ​ 案例:

    shoplist = ['apple', 'mango', 'carrot', 'banana']
    name = 'swaroop'
    
    # Indexing or 'Subscription' operation #
    # 索引或“下标(Subscription)”操作符 #
    print('Item 0 is', shoplist[0])
    print('Item 1 is', shoplist[1])
    print('Item 2 is', shoplist[2])
    print('Item 3 is', shoplist[3])
    print('Item -1 is', shoplist[-1])
    print('Item -2 is', shoplist[-2])
    print('Character 0 is', name[0])
    
    # Slicing on a list #
    print('Item 1 to 3 is', shoplist[1:3])
    print('Item 2 to end is', shoplist[2:])
    print('Item 1 to -1 is', shoplist[1:-1])
    print('Item start to end is', shoplist[:])
    
    # 从某一字符串中切片 #
    print('characters 1 to 3 is', name[1:3])
    print('characters 2 to end is', name[2:])
    print('characters 1 to -1 is', name[1:-1])
    print('characters start to end is', name[:])
    

    ​ 输出:

    $ python ds_seq.py
    Item 0 is apple
    Item 1 is mango
    Item 2 is carrot
    Item 3 is banana
    Item -1 is banana
    Item -2 is carrot
    Character 0 is s
    Item 1 to 3 is ['mango', 'carrot']
    Item 2 to end is ['carrot', 'banana']
    Item 1 to -1 is ['mango', 'carrot']
    Item start to end is ['apple', 'mango', 'carrot', 'banana']
    characters 1 to 3 is wa
    characters 2 to end is aroop
    characters 1 to -1 is waroo
    characters start to end is swaroop
    

    ​ 切片时可以提供第三个数字,这数字就是步长,如果不提供的话就默认为1。

    ​ 案例:

    >>> shoplist = ['apple', 'mango', 'carrot', 'banana']
    >>> shoplist[::1]
    ['apple', 'mango', 'carrot', 'banana']
    >>> shoplist[::2]
    ['apple', 'carrot']
    >>> shoplist[::3]
    ['apple', 'banana']
    >>> shoplist[::-1]
    ['banana', 'carrot', 'mango', 'apple']
    

    ​ 你会注意到当步长为 2 时,我们得到的是第 0、2、4…… 位项目。当步长为 3 时,我们得到的是第 0、3……位项目。

    集合

    ​ 集合(Set)是简单对象的无序集合(Collection)。集合中元素无序且唯一,集合主要是用来测试项目是否存在,子集判断和交集运算等。

    ​ 案例:

    >>> bri = set(['brazil', 'russia', 'india'])
    >>> 'india' in bri
    True
    >>> 'usa' in bri
    False
    >>> bric = bri.copy()
    >>> bric.add('china')
    >>> bric.issuperset(bri)
    True
    >>> bri.remove('russia')
    >>> bri & bric # OR bri.intersection(bric)
    {'brazil', 'india'}
    

    引用

    ​ 就是将一个变量绑定到一个对象。这个变量不是代表那个对象本身,只是指向了内存中存储相应对象的那一部分。

    ​ 案例:

    print('Simple Assignment')
    shoplist = ['apple', 'mango', 'carrot', 'banana']
    # mylist 只是指向同一对象的另一种名称
    mylist = shoplist
    
    # 我购买了第一项项目,所以我将其从列表中删除
    del shoplist[0]
    
    print('shoplist is', shoplist)
    print('mylist is', mylist)
    # 注意到 shoplist 和 mylist 二者都
    # 打印出了其中都没有 apple 的同样的列表,以此我们确认
    # 它们指向的是同一个对象
    
    print('Copy by making a full slice')
    # 通过生成一份完整的切片制作一份列表的副本
    mylist = shoplist[:]
    # 删除第一个项目
    del mylist[0]
    
    print('shoplist is', shoplist)
    print('mylist is', mylist)
    

    ​ 输出:

    $ python ds_reference.py
    Simple Assignment
    shoplist is ['mango', 'carrot', 'banana']
    mylist is ['mango', 'carrot', 'banana']
    Copy by making a full slice
    shoplist is ['mango', 'carrot', 'banana']
    mylist is ['carrot', 'banana']
    

    有关字符串的更多内容

    ​ 你在程序中使用的所有字符串都是 str 类下的对象。可以查阅help(str)获得更多关于字符串的信息。

    ​ 案例:

    # 这是一个字符串对象
    name = 'Swaroop'
    
    if name.startswith('Swa') :
        print('Yes, the string starts with "Swa"')
    
    if 'a' in name :
        print('Yes, it contains the string "a"')
    
    if name.find('war') != -1 :
        print('Yes, it contains the string "war"')
    
    delimiter = '_*_'
    mylist = ['Brazil', 'Russia', 'India', 'China']
    print(delimiter.join(mylist))
    

    ​ 输出:

    $ python ds_str_methods.py
    Yes, the string starts with "Swa"
    Yes, it contains the string "a"
    Yes, it contains the string "war"
    Brazil_*_Russia_*_India_*_China
    

    ​ startswith 方法用于查找字符串是否以给定的字符串内容开头。 in 运算符用以检查给定的字符串是否是查询的字符串中的一部分。
    ​ find 方法用于定位字符串中给定的子字符串的位置。如果找不到相应的子字符串, find会返回 -1。 str 类同样还拥有一个简洁的方法用以 联结(Join) 序列中的项目,其中字符串将会作为每一项目之间的分隔符,并以此生成并返回一串更大的字符串。

    解决问题

    待解决的问题:

    我想要一款程序来备份我所有的重要文件。

    《简明Python教程》解决问题的方式:

    1. 先分析问题,提出一些需要解决的问题。

    2. 设计稳定的方案,确定步骤

    3. 进行编码实现

    4. 进行测试

    解决方案:

    import os
    import time
    
    # 1. 需要备份的文件与目录将被
    # 指定在一个列表中。
    # 例如在 Windows 下:
    # source = ['"C:\\My Documents"', 'C:\\Code']
    # 又例如在 Mac OS X 与 Linux 下:
    source = ['/Users/swa/notes']
    # 在这里要注意到我们必须在字符串中使用双引号
    # 用以括起其中包含空格的名称。
    
    #2. 备份文件必须存储在一个
    #主备份目录中
    #例如在 Windows 下:
    # target_dir = 'E:\\Backup'
    # 又例如在 Mac OS X 和 Linux 下:
    target_dir = '/Users/swa/backup'
    # 要记得将这里的目录地址修改至你将使用的路径
    
    # 3. 备份文件将打包压缩成 zip 文件。
    # 4. zip 压缩文件的文件名由当前日期与时间构成。
    target = target_dir + os.sep + \
    time.strftime('%Y%m%d%H%M%S') + '.zip'
    
    # 如果目标目录还不存在,则进行创建
    if not os.path.exists(target_dir):
    os.mkdir(target_dir) # 创建目录
    
    # 5. 我们使用 zip 命令将文件打包成 zip 格式
    zip_command = 'zip -r {0} {1}'.format(target,
    ' '.join(source))
    
    
    # 运行备份
    print('Zip command is:')
    print(zip_command)
    print('Running:')
    if os.system(zip_command) == 0:
    print('Successful backup to', target)
    else:
    print('Backup FAILED')
    
    

    ​ 输出:

    $ python backup_ver1.py
    Zip command is:
    zip -r /Users/swa/backup/20140328084844.zip /Users/swa/notes
    Running:
    adding: Users/swa/notes/ (stored 0%)
    adding: Users/swa/notes/blah1.txt (stored 0%)
    adding: Users/swa/notes/blah2.txt (stored 0%)
    adding: Users/swa/notes/blah3.txt (stored 0%)
    Successful backup to /Users/swa/backup/20140328084844.zip
    

    针对 Windows 用户的提示
    除了使用双反斜杠转义序列,你还可以使用原始字符串。例如使用 ‘C:\Documents’ 或
    r’C:\Documents’ 。然而,不要使用 ‘C:\Documents’ ,因为它将被识别为你使用了一个
    未知的转义序列 \D 来结束路径的输入。

    可以对上述的程序持续的改进,参照《简明Python教程》的P94.

    软件开发流程

    ​ 我们已经经历了开发一款软件的流程中的各个 阶段(Phases) 。现在可以将这些阶段总结如下:

    1. What/做什么(分析)
    2. How/怎么做(设计)
    3. Do It/开始做(执行)
    4. Test/测试(测试与修复错误)
    5. Use/使用(操作或开发)
    6. Maintain/维护(改进)

    ​ 编写程序时推荐的一种方式是遵循我们在编写备份脚本时所经历的步骤:进行分析与设计;开始实现一个简单版本;测试并修复错误;开始使用以确保工作状况皆如期望那般。现在,你可以添加任何你所希望拥有的功能,并继续去重复这一“开始做—测试—使用”循环,需要做多少次就去做多少次。

    要记住:

    程序是成长起来的,不是搭建出来的。 (Software is grown, not built.) ——Bill dehÓra

    zhg: 这一章节非常的重要,强烈建议看一下《简明Python教程》的“解决问题”章节。

    面向对象编程

    ​ 类与对象是面向对象编程的两个主要方面。一个类(Class)能够创建一种新的类型(Type),其中对象(Object)就是类的实例(Instance)。可以这样来类比:你可以拥有类型 int 的变量,也就是说存储整数的变量是 int 类的实例(对象)。

    ​ 需要注意的是:在Python中int也是一个类型,整数也会被视为对象。

    ​ 在对象中存储数据的普通变量称作“字段”。对象可以调用类的函数来实现功能,这些函数叫做“方法”。

    ​ 总之,字段与方法通称类的属性(Attribute)。

    ​ 字段有两种类型——它们属于某一类的各个实例或对象,或是从属于某一类本身。它们被分别称作实例变量(Instance Variables)与类变量(Class Variables)。

    ​ 通过 class 关键字可以创建一个类。这个类的字段与方法可以在缩进代码块中予以列出。

    self

    ​ 类方法与普通函数只有一种特定的区别——前者必须多加一个参数在参数列表开头,这个名字必须添加到参数列表的开头,但是你不用在你调用这个功能时为这个参数赋值,Python 会为它提供。这种特定的变量引用的是对象本身,按照惯例,它被赋予 self 这一名称。

    ​ 上述参数也可以指定为其他的名称,但是强烈建议使用self,方便其他人识别,也有利于IDE提供编程提示。

    ​ 你一定会在想 Python 是如何给 self 赋值的,以及为什么你不必给它一个值。一个例子或许会让这些疑问得到解答。假设你有一个 MyClass 的类,这个类下有一个实例 myobject 。当你调用一个这个对象的方法,如 myobject.method(arg1, arg2) 时,Python 将会自动将其转换成 MyClass.method(myobject, arg1, arg2) ——这就是 self 的全部特殊之处所在。

    ​ 这同时意味着,如果你有一个没有参数的方法,你依旧必须拥有一个参数—— self 。

    ​ 最简单的类如下:

    class Person:
        pass # 一个空的代码块
    
    p = Person()
    print(p)
    

    ​ 输出:

    $ python oop_simplestclass.py
    <__main__.Person instance at 0x10171f518>
    

    方法

    ​ 类和对象都可以带有方法,但是需要多一个额外的参数。

    ​ 案例:

    class Person:
    	def say_hi(self):
    		print('Hello, how are you?')
    
    p = Person()
    p.say_hi()
    # 前面两行同样可以写作
    # Person().say_hi()
    

    ​ 输出:

    $ python oop_method.py
    Hello, how are you?
    

    ​ 要注意到 say_hi 这一方法不需要参数,但是依旧在函数定义中拥有 self 变量。

    __init__方法

    ​ 这个方法会在对象被示例化的时候被调用,其实就相当于是构造函数。

    ​ 案例:

    class Person:
    	def __init__(self, name):
    		self.name = name
    
       	def say_hi(self):
    		print('Hello, my name is', self.name)
    
    p = Person('Swaroop')
    p.say_hi()
    # 前面两行同时也能写作
    # Person('Swaroop').say_hi()
    

    ​ 输出:

    $ python oop_init.py
    Hello, my name is Swaroop
    

    self.name 中的点号意味着这个叫作“name”的东西是某个叫作“self”的对象的一部分,而另一个 name 则是一个局部变量。

    ​ zhg: 注意上面这个案例中创建对象字段的方式,根本就没先定义,而是直接就开始赋值了。

    类变量与对象变量

    ​ 数据部分——也就是字段——只不过是绑定(Bound)到类与对象的命名空间(Namespace)的普通变量。这些名称仅在这些类与对象所在的上下文中有效,这就是它们被称作“命名空间”的原因。

    ​ 字段有两种类型——类变量和对象变量。

    ​ 类变量是属于类的,所有类的实例可以共享这个变量,类变量只有一个副本,当一个类的实例对类变量进行改变时,其他的实例都可以看到这种改变。

    ​ 对象变量是属于实例或对象的,每个实例都会有对象变量的一个单独副本,在一个实例中对对象变量进行改变时,其他实例中的同名对象变量不会有任何的变化。

    ​ 案例:

    # coding=UTF-8
    class Robot:
        """表示有一个带名字的机器人"""
        # 一个类变量, 用来计数机器人的数量
        population = 0
    
        def __init__(self, name):
            """初始化数据"""
            self.name = name
            print("(Initializing {})".format(self.name))
    
            # 当有人被创建时,机器人
            # 将会增加人口数量
            Robot.population += 1
    
        def die(self):
            """我挂了"""
            print("{} is being destroyed!".format(self.name))
    
            Robot.population -= 1
    
            if Robot.population == 0:
                print("{} was the last one.".format(self.name))
            else:
                print("There are still {:d} robots working.".format(
                    Robot.population))
    
        def say_hi(self):
            """来自机器人的诚挚问候
    
            没问题,你做得到。"""
            print("Greetings, my masters call me {}.".format(self.name))
    
        @classmethod
        def how_many(cls):
            """打印出当前的人口数量"""
            print("We have {:d} robots.".format(cls.population))
    
    
    droid1 = Robot("R2-D2")
    droid1.say_hi()
    Robot.how_many()
    
    droid2 = Robot("C-3P0")
    droid2.say_hi()
    Robot.how_many()
    
    print("\nRobots can do some work here.\n")
    
    print("Robots have finished their work. So let's destroy them.")
    droid1.die()
    droid2.die()
    
    Robot.how_many()
    

    ​ 输出:

    $ python oop_objvar.py
    (Initializing R2-D2)
    Greetings, my masters call me R2-D2.
    We have 1 robots.
    (Initializing C-3PO)
    Greetings, my masters call me C-3PO.
    We have 2 robots.
    
    Robots can do some work here.
    
    Robots have finished their work. So let's destroy them.
    R2-D2 is being destroyed!
    There are still 1 robots working.
    C-3PO is being destroyed!
    C-3PO was the last one.
    We have 0 robots.
    

    ​ 除了 Robot.popluation ,我们还可以使用 self.__class__.population ,因为每个对象都通过
    self.__class__ 属性来引用它的类。

    ​ 我们使用装饰器(Decorator)将 how_many 方法标记为类方法。

    ​ 你可以将装饰器想象为调用一个包装器(Wrapper)函数的快捷方式,因此启用@classmethod 装饰器等价于调用:

    how_many = classmethod(how_many)
    

    ​ 你需要记住你只能使用 self 来引用同一对象的变量与方法。这被称作属性引用(Attribute Reference)。

    ​ 所有的类成员都是公开的,但是如果使用双下划线作为名称前缀,例如__privatevar,那么Python 会使用名称调整(Namemangling)来使其有效地成为一个私有变量。

    针对 C++/Java/C# 程序员的提示
    所有类成员(包括数据成员)都是公开的,并且 Python 中所有的方法都是虚拟的(Virtual)。

    继承

    ​ 面向对象编程的一大优点是对代码的重用(Reuse),重用的一种实现方法就是通过继承(Inheritance)机制。继承最好是想象成在类之间实现类型与子类型(Type and Subtype)关系的工具。

    ​ 对于基类的改动会自动反映到子类型中。在某些情况下可以将子类型对象看作是基类对象,这叫做多态性。

    ​ 案例:

    # coding=UTF-8
    
    class SchoolMember:
        '''代表任何学校里的成员'''
        def __init__(self, name, age):
            self.name = name
            self.age = age
            print('(Initialized SchoolMember: {})'.format(self.name))
    
        def tell(self):
            '''告诉我有关我的细节'''
            print('Name:"{}" Age:"{}"'.format(self.name, self.age), end=" ")
    
    
    class Teacher(SchoolMember) :
        '''代表一位老师。'''
        def __init__(self, name, age, salary):
            SchoolMember.__init__(self, name, age)
            self.salary = salary
            print('(Initialized Teacher: {})'.format(self.name))
    
        def tell(self):
            SchoolMember.tell(self)
            print('Salary: "{:d}"'.format(self.salary))
    
    
    class Student(SchoolMember):
        '''代表一位学生'''
        def __init__(self, name, age, marks):
            SchoolMember.__init__(self, name, age)
            self.marks = marks
            print('(Initialized Student: {})'.format(self.name))
    
        def tell(self):
            SchoolMember.tell(self)
            print('Marks: "{:d}"'.format(self.marks))
    
    
    t = Teacher('Mrs.Shrividya', 40, 30000)
    s =Student('Swaroop', 25, 75)
    
    #打印一行空白行
    print()
    
    members = [t, s]
    for member in members :
        #对全体师生工作
        member.tell()
    

    ​ 输出:

    $ python oop_subclass.py
    (Initialized SchoolMember: Mrs. Shrividya)
    (Initialized Teacher: Mrs. Shrividya)
    (Initialized SchoolMember: Swaroop)
    (Initialized Student: Swaroop)
    
    Name:"Mrs. Shrividya" Age:"40" Salary: "30000"
    Name:"Swaroop" Age:"25" Marks: "75"
    

    ​ 下面这一点很重要,需要牢记——因为我们在 Teacher 和 Student 子类中定义了__init__ 方法,Python 不会自动调用基类 SchoolMember 的构造函数,你必须自己显式地调用它。

    ​ 相反,如果我们没有在一个子类中定义一个 init 方法,Python 将会自动调用基类的构造函数。

    ​ 定义子类时,子类名称后的括号是一个元组,称作继承元组。

    ​ 这里有一条有关术语的注释——如果继承元组(Inheritance Tuple)中有超过一个类,这种情况就会被称作多重继承(Multiple Inheritance)。

    总结:

    ​ Python是高度面向对象,所有的东西都可以看作是对象,包括函数。所以有必要清楚的知道类与对象的知识。

    输入与输出

    ​ 可以用input()获取用户输入,print()打印输出。

    ​ 对于输入,我们还可以使用 str (String,字符串)类的各种方法。

    ​ 下面主要是探讨文件的输入与输出。

    用户输入内容

    ​ 案例:

    def reverse(text):
        return text[::-1]
    
    def is_palindrome(text): # 判断是否是回文
        return text == reverse(text)
    
    something = input('Enter text: ')
    if is_palindrome(something) :
        print('Yes, it is a palindrome')
    else:
        print('No, it is not a palindrome')
    

    ​ 输出:

    $ python3 io_input.py
    Enter text: sir
    No, it is not a palindrome
    
    $ python3 io_input.py
    Enter text: madam
    Yes, it is a palindrome
    
    $ python3 io_input.py
    Enter text: racecar
    Yes, it is a palindrome
    

    ​ input() 函数可以接受一个字符串作为参数,并将其展示给用户。尔后它将等待用户输入内容或敲击返回键。一旦用户输入了某些内容并敲下返回键, input() 函数将返回用户输入的文本。

    文件

    ​ 你可以通过创建一个属于 file 类的对象并适当使用它的 read 、 readline 、 write 方法来打开或使用文件,并对它们进行读取或写入。读取或写入文件的能力取决于你指定以何种方式打开文件。

    ​ 当完成文件操作后,要调用close()方法关闭文件。

    ​ 案例:

    poem = '''\
    Programming is fun
    When the work is done
    if you wanna make your work also fun:
        use Python! 
        '''
    
    # 打开文件以编辑('w'riting)
    f = open('poem.txt', 'w')
    # 向文件中编写文本
    f.write(poem)
    # 关闭文件
    f.close()
    
    # 如果没有特别指定,
    # 将假定启用默认的阅读('r'ead)模式
    f = open('poem.txt')
    while True :
        line = f.readline()
        # 零长度指示 EOF
        if len(line) == 0:
            break
        # 每行(`line`)的末尾
        # 都已经有了换行符
        #因为它是从一个文件中进行读取的
        print(line, end='')
    
    #关闭文件
    f.close()
    

    ​ 输出:

    $ python3 io_using_file.py
    Programming is fun
    When the work is done
    if you wanna make your work also fun:
    	use Python!
    

    ​ open()函数会以指定的模式打开文件,有关更多详细的模式,可以用help(open)进行查看。

    Pickle

    ​ 可以将Python对象输出到文件中,并且稍后可以取回。这叫作持久地存储对象。

    ​ 案例:

    import pickle
    
    # 我们存储相关对象的文件的名称
    shoplistfile = 'shoplist.data'
    # 需要购买的物品清单
    shoplist = ['apple', 'mango', 'carrot']
    
    # 准备写入文件
    f = open(shoplistfile, 'wb')
    # 转储对象至文件
    pickle.dump(shoplist, f)
    f.close()
    
    # 清除 shoplist 变量
    del shoplist
    
    # 重新打开存储文件
    f = open(shoplistfile, 'rb')
    # 从文件中载入对象
    storedlist = pickle.load(f)
    print(storedlist)
    

    ​ 输出:

    $ python io_pickle.py
    ['apple', 'mango', 'carrot']
    

    ​ 要想将一个对象存储到一个文件中,我们首先需要通过 open 以写入(write)二进制(binary)模式打开文件,然后调用 pickle 模块的 dump 函数。这一过程被称作封装(Pickling)。

    ​ 接着,我们通过 pickle 模块的 load 函数接收返回的对象。这个过程被称作拆封(Unpickling)。

    Unicode

    ​ 前面使用和操作字符串的时候都没关关注编码问题。

    注意:如果你正在使用 Python 2,我们又希望能够读写其它非英语语言,我们需要使用
    unicode 类型,它全都以字母 u 开头,例如 u"hello world"

    >>> "hello world"
    'hello world'
    >>> type("hello world") 
    <class 'str'>
    >>> u"hello world"
    'hello world'
    >>> type(u"hello world")
    <class 'str'>
    

    ​ zhg: 上述案例中,type()可以查看对象的类型。

    ​ 若需要制定打开文件的编码是UTF-8,则在open()函数中添加一个关键字参数就可以完成。

    ​ 案例:

    # encoding=utf-8
    import io
    f = io.open("abc.txt", "wt", encoding="utf-8")
    f.write(u"Imagine non-English language here")
    f.close()
    text = io.open("abc.txt", encoding="utf-8").read()
    print(text)
    

    ​ 每当我们诸如上面那番使用 Unicode 字面量编写一款程序时,我们必须确保 Python 程序已经被告知我们使用的是 UTF-8,因此我们必须将 # encoding=utf-8 这一注释放置在我们程序的顶端。

    异常

    ​ 当程序发生错误的时候,Python就会通过异常来告诉你哪儿出现了错误。

    错误

    >>> Print("Hello World")
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    NameError: name 'Print' is not defined
    >>> print("Hello World")
    Hello World
    

    ​ 你会注意到一个 NameError 错误被抛出,同时 Python 还会打印出检测到的错误发生的位置。这就是一个错误错误处理器(Error Handler) 为这个错误所做的事情。

    异常

    ​ 我们将尝试(Try)去读取用户的输入内容。按下 [ctrl-d] 来看看会发生什么事情。

    >>> s = input('Enter something --> ')
    Enter something --> Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    EOFError
    

    处理异常

    ​ 可以通过使用 try…except 来处理异常状况。一般来说我们会把通常的语句放在 try 代码块中,将我们的错误处理器代码放置在 except 代码块中。

    ​ 类似于Java的try{}catch(){}机制。

    ​ 案例:

    try:
        text = input('Enter something --> ')
    except EOFError:
        print('why did you do an EOF on me?')
    except KeyboardInterrupt:
        print('You cancelled the operation. ')
    else: # 没有异常发生
        print('You entered {}'.format(text))
    

    ​ 输出:

    # Press ctrl + d     windows下是ctrl + z代表输入结束
    $ python exceptions_handle.py
    Enter something --> Why did you do an EOF on me?
    # Press ctrl + c
    $ python exceptions_handle.py
    Enter something --> ^CYou cancelled the operation.
    $ python exceptions_handle.py
    Enter something --> No exceptions
    You entered No exceptions
    

    ​ 将所有可能引发异常或错误的语句放在 try 代码块中,并将相应的错误或异常的处理器(Handler)放在 except 子句或代码块中。 except 子句可以处理某种特定的错误或异常,或者是一个在括号中列出的错误或异常。如果没有提供错误或异常的名称,它将处理所有错误与异常。

    ​ 必须至少有一句 except 字句与每一句 try 字句相关联。不然,有一个 try 代码块又有什么意义?

    抛出异常

    ​ 可以通过 raise 语句来引发一次异常。

    ​ 你能够引发的错误或异常必须是直接或间接从属于 Exception (异常) 类的派生类。

    ​ 案例:

    # encoding=utf-8
    
    class ShortInputException(Exception):
        '''一个由用户定义的异常类'''
        def __init__(self, length, atleast):
            Exception.__init__(self)
            self.length = length
            self.atleast = atleast
    
    try:
        text = input('Enter something -->')
        if len(text) < 3:
            raise ShortInputException(len(text), 3)
            # 其他工作能在此处继续正常运行
    except EOFError:
        print('Why did you do an EOF on me?')
    except ShortInputException as ex: # 注意这儿的as
        print(('ShortInputException: The input was '+
              '{0} long, expected ad least {1}')
              .format(ex.length, ex.atleast))
    else:
        print('No exception was raised.')
    

    ​ 输出:

    $ python exceptions_raise.py
    Enter something --> a
    ShortInputException: The input was 1 long, expected at least 3
    
    $ python exceptions_raise.py
    Enter something --> abc
    No exception was raised.
    

    Try … Finally

    ​ Try…Finally块可以确保打开的文件一定被正常的关闭,也就是说无论是否发生异常,finally子句中的代码块都会被执行。

    ​ 案例:

    import sys
    import time
    
    f = None
    try:
        f = open("poem.txt")
        # 我们常用的文件阅读风格
        while True:
            line = f.readline()
            if len(line) == 0:
                break
            print(line, end='')
            sys.stdout.flush()
            print("Press ctrl+c now")
            # 为了确保它能运行一段时间
            time.sleep(3)
    except IOError:
        print("Could not find file poem.txt")
    except KeyboardInterrupt:
        print("!! You cancelled the reading from the file.")
    finally:
        if f:
            f.close()
        print("(Cleaning up: closed the file)")
    

    ​ 输出:

    $ python exceptions_finally.py
    Programming is fun
    Press ctrl+c now
    ^C!! You cancelled the reading from the file.
    (Cleaning up: Closed the file)
    

    with语句

    ​ 在 try 块中获取资源,然后在 finally 块中释放资源是一种常见的模式。因此,还有一个with 语句使得这一过程可以以一种干净的姿态得以完成。

    ​ 案例:

    with open("poem.txt") as f :
        for line in f:
            print(line, end='')
    

    ​ 我们使用的是 open 函数与 with 语句——我们将关闭文件的操作交由 with open 来自动完成。

    ​ 其实是with使用了一个协议,总会在代码块开始之前调用 thefile.__enter__ 函数,并且总会在代码块执行完毕之后调用 thefile.__exit__ 。

    标准库

    ​ Python 标准库(Python Standrad Library)中包含了大量有用的模块,同时也是每个标准的Python 安装包中的一部分。

    Sys模块

    ​ sys 模块包括了一些针对特定系统的功能。我们已经了解过 sys.argv 列表中包括了命令行参数。

    日志模块

    ​ logging 模块可以记录日志。

    ​ 案例:

    import os
    import platform
    import logging
    
    if platform.platform().startswith('Windows'):
        logging_file = os.path.join(os.getenv('HOMEDRIVE'),
                                    os.getenv('HOMEPATH'),
                                    'test.log')
    else:
        logging_file = os.path.join(os.getenv('HOME'),
                                    'test.log')
    
    print("logging to", logging_file)
    
    logging.basicConfig(
        level=logging.DEBUG,
        format='%(asctime)s : %(levelname)s : %(message)s',
        filename=logging_file,
        filemode='w',
    )
    
    logging.debug("Start of the program")
    logging.info("Doing something")
    logging.warning("Dying now")
    

    ​ 输出:

    $ python stdlib_logging.py
    Logging to /Users/swa/test.log
    
    $ cat /Users/swa/test.log
    2014-03-29 09:27:36,660 : DEBUG : Start of the program
    2014-03-29 09:27:36,660 : INFO : Doing something
    2014-03-29 09:27:36,660 : WARNING : Dying now
    

    ​ 我们使用了三款标准库中的模块—— os 模块用以和操作系统交互, platform 模块用以获取平台——操作系统——的信息, logging 模块用来记录(Log)信息。

    每周模块系列:标准库中还有非常多的有用模块,可以阅读Doug Hellmann撰写的优秀的Python Module of the Week或者阅读Python的官方文档。

    更多

    ​ 前面的部分涵盖了将使用到的Python的大部分方面,下面介绍一些其他部分,使得对Python的认识更加全面。

    传递元组

    ​ 你可曾希望从一个函数中返回两个不同的值?你能做到的。只需要使用一个元组。

    >>> def get_error_details():
    ... 	return (2, 'details')
    ...
    >>> errnum, errstr = get_error_details()
    >>> errnum
    2
    >>> errstr
    'details'
    

    ​ 要注意到 a, b = <some expression> 的用法会将表达式的结果解释为具有两个值的一个元组。

    ​ 这也意味着在 Python 中交换两个变量的最快方法是:

    >>> a = 5; b = 8
    >>> a, b
    (5, 8)
    >>> a, b = b, a
    >>> a, b
    (8, 5)
    

    特殊方法

    ​ 诸如 __init__ 和 __del__ 等一些方法对于类来说有特殊意义。

    ​ 特殊方法用来模拟内置类型的某些行为。如果你希望为你的类使用 x[key] 索引操作(就像你在列表与元组中使用的那样),那么你所需要做的只不过是实现__getitem__() 方法,然后你的工作就完成了。如果你试图理解它,就想想 Python 就是对list 类这样做的!

    ​ 如果想了解更多的特殊方法,可以参阅Python手册

    单语句块

    ​ 每个语句块都是由其自身的缩进级别与其他部分进行区分。如果你的语句块只有单独的一句,那么你可以在同一行指定它,例如条件语句与循环语句。

    ​ 案例:

    >>> flag = True
    >>> if flag: print('Yes')
    ...
    Yes
    

    ​ 注意,单个语句是在原地立即使用的,它不会被看作一个单独的块。虽然这个方式可以使得程序更加小巧,但是除非是为了检查错误,建议避免使用这种快捷方式。

    Lambda表格

    ​ lambda 语句可以创建一个新的函数对象。从本质上说, lambda 需要一个参数,后跟一个表达式作为函数体,这一表达式执行的值将作为这个新函数的返回值。

    ​ 案例:

    points = [{'x': 2, 'y': 3},
             {'x': 4, 'y': 1}]
    points.sort(key=lambda i : i['y'])
    print(points)
    

    ​ 输出:

    $ python more_lambda.py
    [{'y': 1, 'x': 4}, {'y': 3, 'x': 2}]
    

    ​ 要注意到一个 list 的 sort 方法可以获得一个 key 参数,用以决定列表的排序方式(通常我们只知道升序与降序)。在我们的案例中,我们希望进行一次自定义排序,为此我们需要编写一个函数,但是又不是为函数编写一个独立的 def 块,只在这一个地方使用,因此我们使用 Lambda 表达式来创建一个新函数。

    列表推导

    ​ 列表推导(List Comprehension)用于从一份现有的列表中得到一份新列表。想象一下,现在你已经有了一份数字列表,你想得到一个相应的列表,其中的数字在大于 2 的情况下将乘以2。列表推导就是这类情况的理想选择。

    ​ 案例:

    listone = [2, 3, 4]
    listtwo = [2*i for i in listone if i > 2]
    print(listtwo)
    

    ​ 输出:

    $ python more_list_comprehension.py
    [6, 8]
    

    ​ 在本案例中,当满足了某些条件时( if i > 2 ),我们进行指定的操作( 2*i ),以此来获得一份新的列表。要注意到原始列表依旧保持不变。

    ​ 使用列表推导的优点在于可以减少代码。

    在函数中接收元组与字典

    ​ 有一种特殊方法,即分别使用 * 或 ** 作为元组或字典的前缀,来使它们作为一个参数为函数所接收。当函数需要一个可变数量的实参时,这将颇为有用。

    >>> def powersum(power, *args):
    ... '''Return the sum of each argument raised to the specified power.'''
    ... total = 0
    ... for i in args:
    ... total += pow(i, power)
    ... return total
    ...
    >>> powersum(2, 3, 4)
    25
    >>> powersum(2, 10)
    100
    

    ​ 我们在 args 变量前添加了一个 * 前缀,函数的所有其它的额外参数都将传递到args 中,并作为一个元组予以储存。如果采用的是 ** 前缀,则额外的参数将被视为字典的键值—值配对。

    assert语句

    ​ assert 语句用以断言(Assert)某事是真的。

    ​ 当assert判断事实为真时,则会继续执行后续代码,如果判断其不是真的,那么就会抛出一个错误。当语句断言失败时,将会抛出 AssertionError 。

    ​ 案例:

    >>> mylist = ['item']
    >>> assert len(mylist) >= 1
    >>> mylist.pop()
    'item'
    >>> assert len(mylist) >= 1
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    AssertionError
    

    ​ zhg: 自己的理解,这个assert就是用来验证自己的猜测和假设的,如果猜测和假设是真的,那么后续的基于假设和猜测的逻辑就不会有有问题,那么assert会通过,并继续执行后续代码;如果猜测和假设是错误的,那么后续的基于假设和猜测的逻辑就是有问题的,那么assert就不会通过,则会抛出错误,进而阻止后续代码的运行。

    装饰器

    ​ 装饰器(Decorators)是应用包装函数的快捷方式。这有助于将某一功能与一些代码一遍又一遍地“包装”。

    ​ 案例:

    from time import sleep
    from functools import wraps
    import  logging
    
    logging.basicConfig()
    log = logging.getLogger("retry")
    
    def retry(f):
        @wraps(f)
        def wrapped_f(*args, **kwargs):
            MAX_ATTEMPS = 5
            for attempt in range(1, MAX_ATTEMPS + 1):
                try:
                    return f(*args, **kwargs)
                except:
                    log.exception("Attemp %s/%s failed :%s",
                                  attempt,
                                  MAX_ATTEMPS,
                                  (args, kwargs))
                    sleep(10 * attempt)
            log.critical("All %s attemps failed : %s",
                         MAX_ATTEMPS,
                         (args, kwargs))
        return wrapped_f
    
    counter = 0
    
    @retry
    def save_to_database(arg):
        print("Write to a database or make a network call or etc.")
        print("This will be automatically retried if exception is thrown.")
        global counter
        counter += 1
        # 这将在第一次调用时抛出异常
        # 在第二次运行时将正常工作(也就是重试)
        if counter < 2:
            raise ValueError(arg)
    
    
    if __name__ == '__main__':
        save_to_database("Some bad value")
    

    ​ 输出:

    $ python more_decorator.py
    Write to a database or make a network call or etc.
    This will be automatically retried if exception is thrown.
    ERROR:retry:Attempt 1/5 failed : (('Some bad value',), {})
    Traceback (most recent call last):
    	File "more_decorator.py", line 14, in wrapped_f
    		return f(*args, **kwargs)
    	File "more_decorator.py", line 39, in save_to_database
    		raise ValueError(arg)
    ValueError: Some bad value
    Write to a database or make a network call or etc.
    This will be automatically retried if exception is thrown.
    
    展开全文
  • python教程全解 了解python 1. 了解Python Python是种解释型(这意味着开发过程中没有了编译这个环节)、面向对象(支持面向对象的风格或代码封装在对象的编程技术)、动态数据类型的交互式(可在命令行中通过...

     

    python教程全解

     

    了解python
     

    1.  了解Python

    Python是一种解释型(这意味着开发过程中没有了编译这个环节)、面向对象(支持面向对象的风格或代码封装在对象的编程技术)、动态数据类型的交互式(可在命令行中通过Python提示符及直接代码执行程序)高级程序设计语言。

    2.  Python标识符

    标识符由字母、数字、下划线组成,但不能以数字开头,且区分大小写。

    以下划线开头的标识符是有特殊意义的。以单下划线开头 _foo 的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用 from xxximport * 而导入;

    以双下划线开头的 __foo 代表类的私有成员;以双下划线开头和结尾的 __foo__ 代表 Python 里特殊方法专用的标识,如__init__() 代表类的构造函数。

    Python 可以同一行显示多条语句,方法是用分号 ; 分开。

    3.  Python中的保留字符

    这些保留字不能用作常数或变数,或任何其他标识符名称。所有 Python的关键字只包含小写字母

     

     

    and

    exec

    not

    assert

    finally

    or

    break

    for

    pass

    class

    from

    print

    continue

    global

    raise

    def

    if

    return

    del

    import

    try

    elif

    in

    while

    else

    is

    with

    except

    lambda

    yield

    4.  Python的缩进与多行语句写法

    4.1  Python中的缩进要求非常严格,必须严格对齐。因为Python的代码块不由{}控制,而是由缩进就可以控制。

    4.2  使用斜杠( \)将一行的语句分为多行显示,如下所示:当然,使用各类括号括起语句之后不需要斜杠换行。

      total = item_one + \

              item_two + \

              item_three

      英文三个双引号用在等式中也可以写多行文本,直接使用和三个单引号作用一样,可以做多行注释。

    5.  Python中的不换行与换行输出

        # 换行输出

        print(x)     

        # 不换行输出

        print(x,end='')

     

    Python变量类型

     

    创建变量就意味着会在内存中开辟空间,同时变量必须赋值才会被创建。

    1.  Python中的变量赋值

    单变量赋值:

    counter = 100#赋值整型变量

    miles = 1000.0#浮点型

    name = "John"#字符串

    多变量赋值:

    a = b = c= 1 #三个变量的值都为1

    a, b, c =1, 2, "john"  #分别为三个变量赋值

     

    2.  Python中的数据类型

    Python有五个标准的数据类型:

    1.  Numbers(数字)

    1)不可改变的数据类型:

    当其类型被改变时,将会赋值给一个新的对象。当对变量赋予了数值后,这个对象就会被创建,可通过del语句删除对这些对象的引用。

    2)Python支持的数字类型:

    int(有符号整型,如0x69,10);long(长整型[也可以代表八进制和十六进制],如-4721885298529L,Python用数字后面的L表示长整型);float(浮点型,如70.2E-12);complex(复数,如4.53e-7j)。

    3)Python数据类型转换:

    int(x [,base ])      将x转换为一个整数  
    long(x [,base ])      将x转换为一个长整数  
    float(x )         将x转换到一个浮点数  
    complex(real [,imag ])    创建一个复数  
    str(x )          将对象 x 转换为字符串  
    repr(x )          将对象 x 转换为表达式字符串  
    eval(str )         用来计算在字符串中的有效Python表达式,并返回一个对象  
    tuple(s )         将序列 s 转换为一个元组  
    list(s )          将序列 s 转换为一个列表  
    chr(x )           将一个整数转换为一个字符  
    unichr(x )         将一个整数转换为Unicode字符  
    ord(x )           将一个字符转换为它的整数值  
    hex(x )           将一个整数转换为一个十六进制字符串  
    oct(x )           将一个整数转换为一个八进制字符串  

    4)Python数学函数

    函数

    返回值 ( 描述 )

    abs(x)

    返回数字的绝对值,如abs(-10) 返回 10

    ceil(x)

    返回数字的向上取整值,如math.ceil(4.1) 返回 5

    cmp(x, y)

    比较函数,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1

    exp(x)

    返回e的x次幂(ex),如math.exp(1) 返回2.718281828459045

    fabs(x)

    返回数字的绝对值,如math.fabs(-10) 返回10.0

    floor(x)

    返回向下取整值,如math.floor(4.9)返回 4

    log(x)

    如math.log(math.e)返回1.0,math.log(100,10)返回2.0

    log10(x)

    返回以10为基数的x的对数,如math.log10(100)返回 2.0

    max(x1, x2,...)

    返回给定参数的最大值,参数可以为序列。

    min(x1, x2,...)

    返回给定参数的最小值,参数可以为序列。

    modf(x)

    返回x的整数部分与小数部分,两部分的数值符号与x相同,整数部分以浮点型表示。

    pow(x, y)

    x**y 运算后的值。

    round(x [,n])

    返回浮点数x的四舍五入值,如给出n值,则代表舍入到小数点后的位数。

    sqrt(x)

    返回数字x的平方根

    5)Python随机数函数

    常用于游戏、数学、安全等领域。

    函数

    描述

    choice(seq)

    从序列的元素中随机挑选一个元素,比如random.choice(range(10)),从0到9中随机挑选一个整数。

    randrange ([start,] stop [,step])

    从指定范围内,按指定基数递增的集合中获取一个随机数,基数缺省值为1

    random()

    随机生成下一个实数,它在[0,1)范围内

    seed([x])

    改变随机数生成器的种子seed。如果你不了解其原理,你不必特别去设定seed,Python会帮你选择seed。

    shuffle(lst)

    将序列的所有元素随机排序

    uniform(x, y)

    随机生成下一个实数,它在[x,y]范围内。

    6)       Python三角函数

    函数

    描述

    acos(x)

    返回x的反余弦弧度值。

    asin(x)

    返回x的反正弦弧度值。

    atan(x)

    返回x的反正切弧度值。

    atan2(y, x)

    返回给定的 X 及 Y 坐标值的反正切值。

    cos(x)

    返回x的弧度的余弦值。

    hypot(x, y)

    返回欧几里德范数 sqrt(x*x + y*y)

    sin(x)

    返回的x弧度的正弦值。

    tan(x)

    返回x弧度的正切值。

    degrees(x)

    将弧度转换为角度,如degrees(math.pi/2) , 返回90.0

    radians(x)

    将角度转换为弧度

    7)       Python数学常量

    常量

    描述

    pi

    数学常量 pi(圆周率,一般以π来表示)

    e

    数学常量 e,e即自然常数(自然常数)。

    2.  String(字符串)

    由数字、字母、下划线组成。

    1)       字符串截取

    Python字符串从左至右截取:索引范围(0,长度-1),从右至左截取(-1,字符串开头)。

    2)       Python中不存在单字符

    Python中即使有单字符,也会被当作字符串处理。

    3)       Python转义字符

    转义字符

    描述

    \

    出现在行尾时表现为续行符,出现在行中时,用于“翻译”特殊字符表示特殊含义,如下面选项所示

    \\

    反斜杠符号

    \'

    单引号

    \"

    双引号

    \a

    响铃

    \b

    退格(Backspace)

    \e

    转义

    \000

    \n

    换行

    \v

    纵向制表符

    \t

    横向制表符

    \r

    回车

    \f

    换页

    \oyy

    八进制数,yy代表的字符,例如:\o12代表换行

    \xyy

    十六进制数,yy代表的字符,例如:\x0a代表换行

    \other

    其它的字符以普通格式输出

    4)       Python字符串运算

    下表实例变量 a 值为字符串 "Hello",b 变量值为 "Python":

    操作符 

    描述

     

    +

    字符串连接。

     

    *

    重复输出字符串。

     

    []

    通过索引获取字符串中字符

     

    [ : ]

    截取字符串中的一部分

     

    in

    成员运算符 - 如果字符串中包含给定的字符返回 True

     

    not in

    成员运算符 - 如果字符串中不包含给定的字符返回 True

     

    r/R

    原始字符串 - 原始字符串:所有的字符串都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符。 原始字符串除在字符串的第一个引号前加上字母"r"(可以大小写)以外,与普通字符串有着几乎完全相同的语法。

     

     

     

     
    a='hello'
    b='world'
    print(a+b)          #helloworld,+号连接字符串
    print(a*2)          #hellohello,*号重复字符串
    print(a[1])         #e,[]索引字符
    print(a[1:4])       #ell,[:]截取字符串
    print("h" in a)     #True,in是否包含
    print("M" not in a) #True,not in是否不包含
    print(r'\n')        #\n,r原始字符串(不解析转义字符)
    

     

    5)       Python字符串格式化(方便print时定义类型,如C语言中printf字符串时在引号内写%s一样)

        print("My name is %s and weight is %d kg!" % ('Zara', 21) )
    输出:
        My name is Zara and weight is 21 kg!

        符  

    描述

          %c

     格式化字符及其ASCII

          %s

     格式化字符串

          %d

     格式化整数

          %u

     格式化无符号整型

          %o

     格式化无符号八进制数

          %x

     格式化无符号十六进制数

          %X

     格式化无符号十六进制数(大写)

          %f

     格式化浮点数字,可指定小数点后的精度

          %e

     用科学计数法格式化浮点数

          %E

     作用同%e,用科学计数法格式化浮点数

          %g

     %f和%e的简写

          %G

     %f 和 %E的简写

          %p

     用十六进制数格式化变量的地址

    6)使用三引号输出一大串带特殊字符的字符串

    当使用三引号将字符串框起来时,就不需要再通过转义字符打很多换行符等符号了,可以直接打换行。对比如下:

    >>> hi = '''hi

    there'''

    >>> hi = 'hi\nthere'

    这两种输出的结果都是换行的字符串,但是使用单引号时,当转义字符很多时,会很痛苦。

    9)       String可使用的内建函数

    方法

    描述

    string.capitalize()

    把字符串的第一个字符大写

    string.center(width)

    返回一个原字符串居中,并使用空格填充至长度 width 的新字符串

    string.count(str, beg=0, end=len(string))

    返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数

    string.decode(encoding='UTF-8', errors='strict')

    以 encoding 指定的编码格式解码 string,如果出错默认报一个 ValueError 的 异 常 , 除 非 errors 指 定 的 是 'ignore' 或 者'replace'

    string.encode(encoding='UTF-8', errors='strict')

    以 encoding 指定的编码格式编码 string,如果出错默认报一个ValueError 的异常,除非 errors 指定的是'ignore'或者'replace'

    string.endswith(obj, beg=0, end=len(string))

    检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False.

    string.expandtabs(tabsize=8)

    把字符串 string 中的 tab 符号转为空格,tab 符号默认的空格数是 8。

    string.find(str, beg=0, end=len(string))

    检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1

    string.format()

    格式化字符串

    string.index(str, beg=0, end=len(string))

    跟find()方法一样,只不过如果str不在 string中会报一个异常.

    string.isalnum()

    如果 string 至少有一个字符并且所有字符都是字母或数字则返

    回 True,否则返回 False

    string.isalpha()

    如果 string 至少有一个字符并且所有字符都是字母则返回 True,

    否则返回 False

    string.isdecimal()

    如果 string 只包含十进制数字则返回 True 否则返回 False.

    string.isdigit()

    如果 string 只包含数字则返回 True 否则返回 False.

    string.islower()

    如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True,否则返回 False

    string.isnumeric()

    如果 string 中只包含数字字符,则返回 True,否则返回 False

    string.isspace()

    如果 string 中只包含空格,则返回 True,否则返回 False.

    string.istitle()

    如果 string 是标题化的(见 title())则返回 True,否则返回 False

    string.isupper()

    如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True,否则返回 False

    string.join(seq)

    以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串

    string.ljust(width)

    返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串

    string.lower()

    转换 string 中所有大写字符为小写.

    string.lstrip()

    截掉 string 左边的空格

    string.maketrans(intab, outtab])

    maketrans() 方法用于创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。

    max(str)

    返回字符串 str 中最大的字母。

    min(str)

    返回字符串 str 中最小的字母。

    string.partition(str)

    有点像 find()和 split()的结合体,从 str 出现的第一个位置起,把 字 符 串 string 分 成 一 个 3 元 素 的 元 组 (string_pre_str,str,string_post_str),如果 string 中不包含str 则 string_pre_str == string.

    string.replace(str1, str2,  num=string.count(str1))

    把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次.

    string.rfind(str, beg=0,end=len(string) )

    类似于 find()函数,不过是从右边开始查找.

    string.rindex( str, beg=0,end=len(string))

    类似于 index(),不过是从右边开始.

    string.rjust(width)

    返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串

    string.rpartition(str)

    类似于 partition()函数,不过是从右边开始查找.

    string.rstrip()

    删除 string 字符串末尾的空格.

    string.split(str="", num=string.count(str))

    以 str 为分隔符切片 string,如果 num有指定值,则仅分隔 num 个子字符串

    string.splitlines([keepends])

    按照行('\r', '\r\n', \n')分隔,返回一个包含各行作为元素的列表,如果参数 keepends 为 False,不包含换行符,如果为 True,则保留换行符。

    string.startswith(obj, beg=0,end=len(string))

    检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查.

    string.strip([obj])

    在 string 上执行 lstrip()和 rstrip()

    string.swapcase()

    翻转 string 中的大小写

    string.title()

    返回"标题化"的 string,就是说所有单词都是以大写开始,其余字母均为小写(见 istitle())

    string.translate(str, del="")

    根据 str 给出的表(包含 256 个字符)转换 string 的字符,

    要过滤掉的字符放到 del 参数中

    string.upper()

    转换 string 中的小写字母为大写

    string.zfill(width)

    返回长度为 width 的字符串,原字符串 string 右对齐,前面填充0

    string.isdecimal()

    isdecimal()方法检查字符串是否只包含十进制字符。这种方法只存在于unicode对象。

    3.  List(列表)

    使用非常频繁,支持数字、字符、字符串甚至列表的集合结构。

    1)       增加或删除列表元素

    直接重新赋值给根据索引值取出的值,或通过append()函数来添加。

    通过del 语句删除列表项,如:dellist1[2]

    2)       列表的脚本操作符

    和对字符串的操作类似。

    Python 表达式

    结果

    描述

    len([1, 2, 3])

    3

    长度

    [1, 2, 3] + [4, 5, 6]

    [1, 2, 3, 4, 5, 6]

    组合

    ['Hi!'] * 4

    ['Hi!', 'Hi!', 'Hi!', 'Hi!']

    重复

    3 in [1, 2, 3]

    True

    判断元素是否存在于列表中

    for x in [1, 2, 3]: print x,

    1 2 3

    迭代

    3)       列表的截取

    Python 表达式

    结果

    描述

    L[2]

    'Taobao'

    读取列表中第三个元素

    L[-2]

    'Runoob'

    读取列表中倒数第二个元素

    L[1:]

    ['Runoob', 'Taobao']

    从第二个元素开始截取列表

    4)       Python中列表的函数及方法

     Python包含以下函数:

    函数

    描述

    cmp(list1, list2)

    比较两个列表的元素

    len(list)

    列表元素个数

    max(list)

    返回列表元素最大值

    min(list)

    返回列表元素最小值

    list(seq)

    将元组转换为列表

    Python包含以下方法:

    函数

    描述

    list.append(obj)

    在列表末尾添加新的对象

    list.count(obj)

    统计某个元素在列表中出现的次数

    list.extend(seq)

    在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)

    list.index(obj)

    从列表中找出某个值第一个匹配项的索引位置

    list.insert(index, obj)

    将对象插入列表

    list.pop(obj=list[-1])

    移除列表中的一个元素(默认最后一个元素),并且返回该元素的值

    list.remove(obj)

    移除列表中某个值的第一个匹配项

    list.reverse()

    反向列表中元素

    list.sort([func])

    对原列表进行排序

    4.  Tuple(元组)

    1)与列表的区别

    类似列表,但列表用[ ]标识,元组用()标识,并且列表元素可二次赋值,但元组元素不能。

    2)元组的创建

    创建空元组:tuple() 。

    创建只有一个元素的元组:tuple(a,),必须要在元素后加逗号。

    3)元素的访问

    虽然创建时用()包含,但是在访问单个元素时,与列表一样,通过[ 索引号 ]来访问。

    4)删除元组

    元组中的单个元素不能被删除,但是元组可以通过del语句整个删除。

    5)元组运算符(同列表)

     

    6)任意无符号的对象,以逗号隔开,默认为元组(无关闭分隔符)

    7)元组内置函数

    函数

    描述

    cmp(tuple1, tuple2)

    比较两个元组元素。

    len(tuple)

    计算元组元素个数。

    max(tuple)

    返回元组中元素最大值。

    min(tuple)

    返回元组中元素最小值。

    tuple(seq)

    将列表转换为元组。

    5.  Dictionary(字典)

    1)       与列表的差别

    列表是有序的对象集合,字典是无序的对象结合。字典中的元素通过Key来获取,而列表中的元素通过位移来获取。

    2)       字典的定义

    下面是两种定义字典的方法,两种方法都与列表的定义方法类似。

    dict = {}

    dict['one'] ="This is one"

    dict[2] ="This is two"

     

    tinydict = {'name':'john','code':6734,'dept':'sales'}

    3)       数据类型的转换

    函数

    描述

    int(x [,base])

    将x转换为一个整数

    long(x [,base] )

    将x转换为一个长整数

    float(x)

    将x转换到一个浮点数

    complex(real [,imag])

    创建一个复数

    str(x)

    将对象 x 转换为字符串

    repr(x)

    将对象 x 转换为表达式字符串

    eval(str)

    用来计算在字符串中的有效Python表达式,并返回一个对象

    tuple(s)

    将序列 s 转换为一个元组

    list(s)

    将序列 s 转换为一个列表

    set(s)

    转换为可变集合

    dict(d)

    创建一个字典。d 必须是一个序列 (key,value)元组。

    frozenset(s)

    转换为不可变集合

    chr(x)

    将一个整数转换为一个字符

    unichr(x)

    将一个整数转换为Unicode字符

    ord(x)

    将一个字符转换为它的整数值

    hex(x)

    将一个整数转换为一个十六进制字符串

    oct(x)

    将一个整数转换为一个八进制字符串

    Python运算符

    Python支持以下八种运算符:

    1.  算数运算符

    假设a=10,b=20

    运算符

    描述

    实例

    +

    加 - 两个对象相加

    a + b 输出结果 30

    -

    减 - 得到负数或是一个数减去另一个数

    a - b 输出结果 -10

    *

    乘 - 两个数相乘或是返回一个被重复若干次的字符串

    a * b 输出结果 200

    /

    除 - x除以y

    b / a 输出结果 2(整数除整数,只能得整数,要求小数需要将其中一个改为浮点数)

    %

    取模 - 返回除法的余数

    b % a 输出结果 0

    **

    幂 - 返回x的y次幂

    a**b 为10的20次方, 输出结果 100000000000000000000

    //

    取整除 - 返回商的整数部分

    9//2 输出结果 4 , 9.0//2.0输出结果 4.0

    2.  比较运算符

    运算符

    描述

    实例

    ==

    等于 - 比较对象是否相等

    (a == b) 返回 False

    !=

    不等于 - 比较两个对象是否不相等

    (a != b) 返回 true.

    <> 

    不等于 - 比较两个对象是否不相等

    (a <> b) 返回 true。这个运算符类似 != 。

    大于 - 返回x是否大于y

    (a > b) 返回 False

    小于 - 返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量True和False等价。注意,这些变量名的大写。

    (a < b) 返回 true

    >=

    大于等于 - 返回x是否大于等于y。

    (a >= b) 返回 False

    <=

    小于等于 - 返回x是否小于等于y。

    (a <= b) 返回 true

    3.  Python赋值运算符

    运算符

    描述

    实例

    =

    简单的赋值运算符

    c = a + b 将 a + b的运算结果赋值为 c

    +=

    加法赋值运算符

    c += a 等效于 c = c + a

    -=

    减法赋值运算符

    c -= a 等效于 c = c - a

    *=

    乘法赋值运算符

    c *= a 等效于 c = c * a

    /=

    除法赋值运算符

    c /= a 等效于 c = c / a

    %=

    取模赋值运算符

    c %= a 等效于 c = c % a

    **=

    幂赋值运算符

    c **= a 等效于 c = c ** a

    //=

    取整除赋值运算符

    c //= a 等效于 c = c // a

    4.  Python位运算符

    按位运算符是把数字看作二进制来进行计算的。Python中的按位运算法则如下:

    运算符

    描述

    实例

    &

    按位与运算符:参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0

    (a & b) 输出结果 12,二进制解释: 0000 1100

    |

    按位或运算符:只要对应的二个二进位有一个为1时,结果位就为1。

    (a | b) 输出结果 61,二进制解释: 0011 1101

    ^

    按位异或运算符:当两对应的二进位相异时,结果为1

    (a ^ b) 输出结果 49,二进制解释: 0011 0001

    ~

    按位取反运算符:对数据的每个二进制位取反,即把1变为0,把0变为1 。~x 类似于 -x-1

    (~a ) 输出结果 -61,二进制解释: 1100 0011,在一个有符号二进制数的补码形式。

    << 

    左移动运算符:运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。

    a << 2 输出结果 240,二进制解释: 1111 0000

    >> 

    右移动运算符:把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数

    a >> 2 输出结果 15,二进制解释: 0000 1111

    5.  Python逻辑运算符

    运算符

    逻辑表达式

    描述

    实例

    and

    x and y

    布尔"与" - 如果 x 为 False,x and y 返回 False,否则它返回 y 的计算值。

    (a and b) 返回 20

    or

    x or y

    布尔"或" - 如果 x 是非 0,它返回 x 的值,否则它返回 y 的计算值。

    (a or b) 返回 10

    not

    not x

    布尔"非" - 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True。

    not(a and b) 返回 False

    6.  Python成员运算符

    运算符

    描述

    实例

    in

    如果在指定的序列中找到值返回 True,否则返回 False。

    x 在 y序列中 , 如果 x 在 y 序列中返回 True。

    not in

    如果在指定的序列中没有找到值返回 True,否则返回 False。

    x 不在 y序列中 , 如果 x 不在 y 序列中返回 True。

    7.  Python身份运算符(判断引用的对象)

    1) is与==的区别

    ==判断两者是否完全相等,而is判断两个对象引用的对象是否是同一个。

    运算符

    描述

    实例

    is

    is 是判断两个标识符是不是引用自一个对象

    x is y,类似 id(x) == id(y) , 如果引用的是同一个对象则返回 True,否则返回 False

    is not

    is not 是判断两个标识符是不是引用自不同对象

    x is not y , 类似 id(a) != id(b)。如果引用的不是同一个对象则返回结果 True,否则返回 False。

    8.  Python运算符优先级

    运算符

    描述

    **

    指数 (最高优先级)

    ~ + -

    按位翻转, 一元加号和减号 (最后两个的方法名为 +@ 和 -@)

    * / % //

    乘,除,取模和取整除

    + -

    加法减法

    >> <<

    右移,左移运算符

    &

    位 'AND'

    ^ |

    位运算符

    <= < > >=

    比较运算符

    <> == !=

    等于运算符

    = %= /= //= -= += *= **=

    赋值运算符

    is is not

    身份运算符

    in not in

    成员运算符

    not or and

    逻辑运算符

     

    Python语句

    1.  条件语句

    Python不支持switch语句,因此判断结果对应多种执行方式时,只能用elif来做。

     

    num = 5
    if num ==3:         #判断num的值
        print('boss')
    elif num ==2:
        print('user')
    elif num ==1:
        print('worker')

     

    2.  循环语句

    Python中没有do while循环。

    循环类型

    描述

    while循环

    在给定的判断条件为 true 时执行循环体,否则退出循环体。

    for循环

    重复执行语句

    嵌套循环

    你可以在while循环体中嵌套for循环(for中也可以嵌套for吧)

    循环控制语句:

    控制语句

    描述

    break语句

    在语句块执行过程中终止循环,并且跳出整个循环

    continue语句

    在语句块执行过程中终止当前循环,跳出该次循环,执行下一次循环。

    pass语句

    pass是空语句,是为了保持程序结构的完整性。

    1)pass语句在函数中的作用

    当你在编写一个程序时,执行语句部分思路还没有完成,这时你可以用pass语句来占位,也可以当做是一个标记,是要过后来完成的代码。比如下面这样:

     

    def iplaypython():
        pass

    定义一个函数iplaypython,但函数体部分暂时还没有完成,又不能空着不写内容,因此可以用pass来替代占个位置。

     

    2)pass语句在循环中的作用

    pass也常用于为复合语句编写一个空的主体,比如说你想一个while语句无限循环,每次迭代时不需要任何操作,你可以这样写:

    while True:
        pass

    以上只是举个例子,现实中最好不要写这样的代码,因为执行代码块为pass也就是空什么也不做,这时python会进入死循环。

     

    3)pass语句用法总结

    1、空语句,什么也不做
    2
    、在特别的时候用来保证格式或是语义的完整性

    4)While循环(可在循环中使用else语句)

    # continue 和 break用法

     

    i=1
    while i<10:
        i+= 1
        if i%2>0:  # 非双数时跳过输出
            continue
        print(i)  # 输出双数2、4、6、8、10
    
    i = 1
    while 1:  # 循环条件为1必定成立
        print(i)  # 输出1~10
        i+= 1
        if i>10:  # 当i大于10时跳出循环
            break

     

    在循环中使用else语句,即当条件不满足之后,结束循环,执行else语句

     

    count = 0
    while count <5:
        print(count," is less than 5")
        count = count +1
    else:
        print(count," is not less than 5")

     

    5)for循环(可在循环中使用else语句)

    可以通过直接取值迭代,也可以通过序列索引迭代

    取值迭代:

     

    for letter in 'Python':  # 逐个输出字符串中的字符
        print('当前字母 :', letter)
    
    fruits = ['banana', 'apple', 'mango']
    for fruit in fruits:  # 逐个输出列表中的元素
        print('当前水果 :', fruit)
    print("Good bye!")

     

     

     

     

    索引迭代:

     

    fruits = ['banana','apple','mango']
    #通过len()函数获得列表的长度,通过range()函数获得了一个值不超过长度-1的索引序列
    for index in range(len(fruits)):
        print('当前水果 :',fruits[index])
        print("Good bye!")

     

     

     

    Python日期和时间

    Python是以时间戳来记录时间的,也就是当前时间距离1970年1月1日过去了多少秒,因此获取时间的方法一般是先获取时间戳,再将时间戳转换为时间元组,再将时间元组转换为不同格式的时间数据

    1.获取时间戳

    import time; #引入time模块

    ticks = time.time()

    2.获取时间

    什么是时间元组?

    很多Python函数用一个元组装起来的9组数字处理时间,也就是struct_time元组:

    属性

    字段

    tm_year

    4位数年

    2008

    tm_mon

    1 到 12

    tm_mday

    1到31

    tm_hour

    小时

    0到23

    tm_min

    分钟

    0到59

    tm_sec

    0到61 (60或61 是闰秒)

    tm_wday

    一周的第几日

    0到6 (0是周一)

    tm_yday

    一年的第几日

    1到366 (儒略历)

    tm_isdst

    夏令时

    -1, 0, 1, -1是决定是否为夏令时的旗帜


    代码接上,将获取的时间戳转换为时间元组:

    localtime = time.localtime(time.time())

    print("本地时间为 :", localtime)

    3.获取格式化的时间

    localtime = time.asctime( time.localtime(time.time()))

    print("本地时间为 :", localtime)

    4.获取更多格式的格式化时间

    time.strftime(format[, t])  #总的代码形式

     

    # 格式化成2016-03-20 11:45:39形式

    print(time.strftime("%Y-%m-%d%H:%M:%S", time.localtime()))

    python中时间日期格式化符号:

    ·       %y两位数的年份表示(00-99

    ·       %Y四位数的年份表示(000-9999

    ·       %m月份(01-12

    ·       %d月内中的一天(0-31

    ·       %H 24小时制小时数(0-23

    ·       %I 12小时制小时数(01-12

    ·       %M分钟数(00=59

    ·       %S秒(00-59

    ·       %a本地简化星期名称

    ·       %A本地完整星期名称

    ·       %b本地简化的月份名称

    ·       %B本地完整的月份名称

    ·       %c本地相应的日期表示和时间表示

    ·       %j年内的一天(001-366

    ·       %p本地A.M.或P.M.的等价符

    ·       %U一年中的星期数(00-53)星期天为星期的开始

    ·       %w星期(0-6),星期天为星期的开始

    ·       %W一年中的星期数(00-53)星期一为星期的开始

    ·       %x本地相应的日期表示

    ·       %X本地相应的时间表示

    ·       %Z当前时区的名称

    ·       %% %号本身

    5.获取某个月的日历

    import calendar

    cal = calendar.month(2016,1)

    6.Time和Calendar模块的函数及属性

    函数

    描述

    time.altzone

    返回格林威治西部的夏令时地区的偏移秒数。如果该地区在格林威治东部会返回负值(如西欧,包括英国)。对夏令时启用地区才能使用。

    time.asctime([tupletime])

    接受时间元组并返回一个可读的形式为"Tue Dec 11 18:07:14 2008"(2008年12月11日 周二18时07分14秒)的24个字符的字符串。

    time.clock( )

    用以浮点数计算的秒数返回当前的CPU时间。用来衡量不同程序的耗时,比time.time()更有用。

    time.ctime([secs])

    作用相当于asctime(localtime(secs)),未给参数相当于asctime()

    time.gmtime([secs])

    接收时间辍(1970纪元后经过的浮点秒数)并返回格林威治天文时间下的时间元组t。注:t.tm_isdst始终为0

    time.localtime([secs])

    接收时间辍(1970纪元后经过的浮点秒数)并返回当地时间下的时间元组t(t.tm_isdst可取0或1,取决于当地当时是不是夏令时)。

    time.mktime(tupletime)

    接受时间元组并返回时间辍(1970纪元后经过的浮点秒数)。

    time.sleep(secs)

    推迟调用线程的运行,secs指秒数。

    time.strftime(fmt[,tupletime])

    接收以时间元组,并返回以可读字符串表示的当地时间,格式由fmt决定。

    time.strptime(str,fmt='%a %b %d %H:%M:%S %Y')

    根据fmt的格式把一个时间字符串解析为时间元组。

    time.time( )

    返回当前时间的时间戳(1970纪元后经过的浮点秒数)。

    time.tzset()

    根据环境变量TZ重新初始化时间相关设置

    Time模块包含了以下2个非常重要的属性:

    属性

    描述

    time.timezone

    属性time.timezone是当地时区(未启动夏令时)距离格林威治的偏移秒数(>0,美洲;<=0大部分欧洲,亚洲,非洲)。

    time.tzname

    属性time.tzname包含一对根据情况的不同而不同的字符串,分别是带夏令时的本地时区名称,和不带的。

    函数

    描述

    calendar.calendar(year,w=2,l=1,c=6)

    返回一个多行字符串格式的year年年历,3个月一行,间隔距离为c。 每日宽度间隔为w字符。每行长度为21* W+18+2* C。l是每星期行数。

    calendar.firstweekday( )

    返回当前每周起始日期的设置。默认情况下,首次载入caendar模块时返回0,即星期一。

    calendar.isleap(year)

    是闰年返回True,否则为false。

    calendar.leapdays(y1,y2)

    返回在Y1,Y2两年之间的闰年总数。

    calendar.month(year,month,w=2,l=1)

    返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数。

    calendar.monthcalendar(year,month)

    返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数。Year年month月外的日期都设为0;范围内的日子都由该月第几日表示,从1开始。

    calendar.monthrange(year,month)

    返回两个整数。第一个是该月的星期几的日期码,第二个是该月的日期码。日从0(星期一)到6(星期日);月从1到12。

    calendar.prcal(year,w=2,l=1,c=6)

    相当于 print calendar.calendar(year,w,l,c).

    calendar.prmonth(year,month,w=2,l=1)

    相当于 print calendar.calendar(year,w,l,c)。

    calendar.setfirstweekday(weekday)

    设置每周的起始日期码。0(星期一)到6(星期日)。

    calendar.timegm(tupletime)

    和time.gmtime相反:接受一个时间元组形式,返回该时刻的时间辍(1970纪元后经过的浮点秒数)。

    calendar.weekday(year,month,day)

    返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)。

    7.其他可以处理时间的模块

    ·       datetime模块

    ·       pytz模块

    ·       dateutil模块

     

     

    Python函数

     
     

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

    函数能提高应用的模块性,和代码的重复利用率。

    1.Python函数定义

    def functionname(parameters):

       "函数_文档字符串"

       function_suite

       return [expression]

    2.对象创建

    在 python 中,类型属于对象,变量是没有类型的

    a=[1,2,3] #赋值后这个对象就已经创建好了

    a="Runoob"

    以上代码中,[1,2,3] 是 List 类型,"Runoob" 是 String 类型,而变量 a 是没有类型,她仅仅是一个对象的引用(一个指针),可以是 List 类型对象,也可以指向 String 类型对象。

    3.可更改对象和不可更改对象

    在 python 中,strings,tuples, 和 numbers 是不可更改(重新赋值后,原值不再存在)的对象,而 list,dict等则是可以修改(重新赋值后,原来的值依旧存在,依旧可以获取到)的对象。

    ·       不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际是新生成一个 int 值对象 10,再让 a 指向它,而 5 被丢弃,不是改变a的值,相当于新生成了a

    ·       可变类型:变量赋值 la=[1,2,3,4] 后再赋值 la[2]=5 则是将 list la 的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。

    4.可更改对象和不可更改对象的参数传递

    python函数的参数传递:

    不可变类型:类似 c++的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a本身

     

    def ChangeInt(a):
    a = 10

    b = 2
    ChangeInt(b)
    print(b)   #结果是 2

     

    int2对象指向变量b,而调用changeInt函数时,变量a就是变量b,此时的变量a和变量b都对应int 2对象,但是在之后a被重新赋值为10,此时变量a指向对象int 10,产生了一个新的int型对象,而变量b所指向的对象不变。

     

    可变类型:类似 c++的引用传递,如 列表,字典。如 fun(la),则是将 la真正的传过去,修改后fun外部的la也会受影响

    python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。

     

    def changeme( mylist): 
    mylist.append([1,2,3,4]);  #"修改传入的列表"
        print("函数内取值: ", mylist)
        return
     
    # 调用changeme函数
    mylist = [10,20,30];
    changeme(mylist);
    print("函数外取值: ", mylist)

     

    因为上面的代码传递的是可变对象,因此在函数内取值和函数外取值都是同样的结果。

    5.调用函数时的参数使用

    1)必备参数

    必须与函数声明时一致的顺序来传递参数。

    2)关键字参数

    传参数时可与函数声明的顺序不一样,因为Python解释器可以用参数名来匹配参数值。

    3)缺省参数

    传入参数时未给参数赋值,则保持默认值。

    #可写函数说明

     

    def printinfo( name, age=35):
    print("Name: ", name);  #"打印任何传入的字符串"
        print("Age ", age);
        return;
     
    #调用printinfo函数
    printinfo(age=50,name="miki");
    printinfo(name="miki");

     

    这里第二句的age没有输入值,则输出默认值35。

    4)不定长参数(也就是包含非必备参数的参数定义)

    当不确定会传入参数的个数时,可以对可以不输入的参数名前面加“*”号,按顺序输入时进行对应即可。

     

    def printinfo( arg1,*vartuple):
    print("输出: ",arg1)  #"打印任何传入的参数"
        for var in vartuple:
          print var
        return;
     
    # 调用printinfo函数
    printinfo(10);
    printinfo(70,60,50);

     

    5.匿名函数(使用lambda创建)

    python 使用 lambda来创建匿名函数。

    lambda只是一个表达式,函数体比def简单很多。 

    lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。

    lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数(只能访问自己的命名空间里的参数)

    虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

    # 用一个语句来定义一个Sum函数

     

    sum = lambda arg1, arg2: arg1+ arg2;
        
    # 调用sum函数
    print("相加后的值为 : ", sum(10,20))
    print("相加后的值为 : ", sum(20,20))

     

    6.变量作用域

    1)全局变量

    定义在所有函数外则为全局变量,可在所有代码中使用。

    当需要在函数内定义全局变量时,必须用global语句。

    2)局部变量

    定义在函数内则为局部变量,只能在相应的代码块内使用。

     

    total = 0; # 这是一个全局变量
    # 可写函数说明
    def sum( arg1, arg2):   #返回2个参数的和."
        total = arg1 + arg2; # total在这里是局部变量.
        print("函数内是局部变量 : ", total)
        return(total);
     
    #调用sum函数
    sum( 10, 20);
    print("函数外是全局变量 : ", total)

     

    在上面的例子中,在函数内部,total是局部变量,而在外部total是全局变量,局部变量的改变不会改变全局变量的值,因此第一个打印结果是30,而第二个是0。

    Python模块

    Python 模块(Module),是一个Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句。

    模块让你能够有逻辑地组织你的Python 代码段。

    把相关的代码分配到一个模块里能让你的代码更好用,更易懂。

    1.导入模块的三种方法的区别

    1)import导入

    import support   导入模块,并不导入单个函数

     

    # 现在可以调用模块里包含的函数了 ,但是必须通过模块名.函数名的方式调用

    support.print_func("Runoob")

    2)From … import导入

    下面的语句可以将模块中的某一部分导入,它只会将里这个部分单个引入到执行这个声明的模块的全局符号表。这个部分可以是某个函数块,也可以是函数块的子函数块。

    from modname import name1[, name2[, ... nameN]]

    3)From … import * 导入

    前两种语句都是导入模块的部分,只是部分导入的位置不同,而使用From …import*则是导入模块的全部项目,尽量少用,太耗内存。

    2.命名空间和作用域

    变量是拥有匹配对象的名字(标识符)。

    命名空间是一个包含了变量名称们(键)和它们各自相应的对象们(值)的字典。每个函数都会有自己的命名空间,当变量出现在函数内部时,Python默认其为局部变量,若存在一个与局部变量重名的全局变量,则由局部变量覆盖全局变量。

    Python的命名空间分局部命名空间和全局命名空间。

    3.找出模块中所有的模块名、函数名、变量名(dir()函数)

    # 导入内置math模块
    import math
    content = dir(math)
    print content;
    
     

    以上实例输出结果:

    ['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan', 
    'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 
    'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log',
    'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 
    'sqrt', 'tan', 'tanh']

    在这里,特殊字符串变量__name__指向模块的名字,__file__指向该模块的导入文件名。

     

    4.查看全局变量和局部变量命名空间

    根据调用地方的不同globals()和 locals()函数可被用来返回全局和局部命名空间里的名字。

    如果在函数内部调用 locals(),返回的是所有能在该函数里访问的命名。

    如果在函数内部调用 globals(),返回的是所有在该函数里能访问的全局名字。

    两个函数的返回类型都是字典。所以名字们能用 keys() 函数摘取。

    5. reload() 函数

    当一个模块被导入到一个脚本,模块顶层部分的代码只会被执行一次。

    因此,如果你想重新执行模块里顶层部分的代码,可以用 reload() 函数。该函数会重新导入之前导入过的模块。语法如下:在这里,module_name要直接放模块的名字,而不是一个字符串形式。

    reload(module_name)

    Python I/O函数(不只是文件读写)

    1.读取键盘输入

    读取输入的行:

     

    str = input("请输入:");
    print("你输入的内容是: ", str)
    
    
     
    input() 函数可以接受Python表达式的输入,并输出表达式的计算结果
    请输入:[x*5 for x in range(2,10,2)]
    你输入的内容是:  [10, 20, 30, 40]

    2.打开、关闭读写文件

    可以用file对象对大多数文件进行操作。

    1)打开文件

    你必须先用Python内置的open()函数打开一个文件,创建一个file对象,相关的方法才可以调用它进行读写。

    file object = open(file_name [, access_mode][, buffering])

    ·       file_name:file_name变量是一个包含了你要访问的文件名称的字符串值。

    ·       access_mode:access_mode决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)

    ·       buffering:如果buffering的值被设为0,就不会有寄存。如果buffering的值取1,访问文件时会寄存行。如果将buffering的值设为大于1的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。

    ·       当文件不存在但通过open函数打开时,如果是写入则会自动创建文件,如果是读取内容则会报错。

    打开文件的模式                             

    描述

    r

    只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。

    rb

    二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。

    r+

    打开一个文件用于读写。文件指针将会放在文件的开头。

    rb+

    以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。

    w

    打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

    wb

    以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

    w+

    打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

    wb+

    以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。

    a

    打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

    ab

    以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。

    a+

    打开一个文件用于读写如果该文件已存在,文件指针将会放在文件的结尾(不然怎么追加呢)。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。

    ab+

    以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

    2)File对象的属性

    文件被打开后就会创建一个File对象。

    对象属性

    描述

    file.closed

    返回true如果文件已被关闭,否则返回false。

    file.mode

    返回被打开文件的访问模式。

    file.name

    返回文件的名称。

    file.softspace

    如果用print输出后,必须跟一个空格符,则返回false。否则返回true。

    3)关闭文件

    当一个文件对象的引用被重新指定给另一个文件时,Python 会关闭之前的文件(Python会自动地关闭之前的文件对象,这样不那么耗费内存)。用close()方法关闭文件是一个很好的习惯。

    4)读写文件

    无论读、写、还是关闭文件,都需要先用open打开文件。

    # 写一个文件
    fo = open("foo.txt", "wb")
    fo.write( "www.runoob.com!\nVery good site!\n");
    
     
    # 关闭打开的文件
    fo.close()

     

    # 读一个文件
    fo = open("foo.txt", "r+")
    str = fo.read(10);     #这里的参数10表示的是被读取的字节数
    print("读取的字符串是 : ", str)
    # 关闭打开的文件
    fo.close()

    5)文件内定位

    tell()方法告诉你文件内的当前位置(那应该就是告诉你文件指针在哪个位置);换句话说,下一次的读写会发生在文件开头这么多字节之后。

    seek(offset [,from])方法改变当前文件的位置。Offset变量表示要移动的字节数。From变量指定开始移动字节的参考位置。如果from被设为0,这意味着将文件的开头作为移动字节的参考位置。如果设为1,则使用当前的位置作为参考位置。如果它被设为2,那么该文件的末尾将作为参考位置。

    # 打开一个文件
    fo = open("foo.txt", "r+")
    str = fo.read(10);
    print("读取的字符串是 : ", str)
    
     
    # 查找当前位置
    position = fo.tell();
    print("当前文件位置 : ", position)
    
     
    # 把指针再次重新定位到文件开头
    position = fo.seek(0, 0);
    str = fo.read(10);
    print("重新读取字符串 : ", str)
    # 关闭打开的文件
    fo.close()

    3.文件File对象的方法

    方法                                                  

    描述

    file.close()

    关闭文件。关闭后文件不能再进行读写操作。

    file.flush()

    刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。

    file.fileno()

    返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。

    file.isatty()

    如果文件连接到一个终端设备返回 True,否则返回 False。

    file.next()

    返回文件下一行。

    file.read([size])

    从文件读取指定的字节数,如果未给定或为负则读取所有。

    file.readline([size])

    读取整行,包括 "\n" 字符。

    file.readlines([sizehint])

    读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比sizhint较大, 因为需要填充缓冲区。

    file.seek(offset[, whence])

    设置文件当前位置

    file.tell()

    返回文件当前位置。

    file.truncate([size])

    截取文件,截取的字节通过size指定,默认为当前文件位置。

    file.write(str)

    将字符串写入文件,没有返回值。

    file.writelines(sequence)

    向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。

    4.文件OS(Python中处理文件和目录的模块)

    方法

    描述

    os.access(path, mode)

    检验权限模式

    os.chdir(path)

    改变当前工作目录

    os.chflags(path, flags)

    设置路径的标记为数字标记。

    os.chmod(path, mode)

    更改权限

    os.chown(path, uid, gid)

    更改文件所有者

    os.chroot(path)

    改变当前进程的根目录

    os.close(fd)

    关闭文件描述符 fd

    os.closerange(fd_low, fd_high)

    关闭所有文件描述符,从 fd_low (包含) 到 fd_high (不包含), 错误会忽略

    os.dup(fd)

    复制文件描述符 fd

    os.dup2(fd, fd2)

    将一个文件描述符 fd 复制到另一个 fd2

    os.fchdir(fd)

    通过文件描述符改变当前工作目录

    os.fchmod(fd, mode)

    改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。

    os.fchown(fd, uid, gid)

    修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。

    os.fdatasync(fd)

    强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。

    os.fdopen(fd[, mode[, bufsize]])

    通过文件描述符 fd 创建一个文件对象,并返回这个文件对象

    os.fpathconf(fd, name)

    返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1, Unix 95, Unix 98, 和其它)。

    os.fstat(fd)

    返回文件描述符fd的状态,像stat()。

    os.fstatvfs(fd)

    返回包含文件描述符fd的文件的文件系统的信息,像 statvfs()

    os.fsync(fd)

    强制将文件描述符为fd的文件写入硬盘。

    os.ftruncate(fd, length)

    裁剪文件描述符fd对应的文件, 所以它最大不能超过文件大小。

    os.getcwd()

    返回当前工作目录

    os.getcwdu()

    返回一个当前工作目录的Unicode对象

    os.isatty(fd)

    如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true, 否则False。

    os.lchflags(path, flags)

    设置路径的标记为数字标记,类似 chflags(),但是没有软链接

    os.lchmod(path, mode)

    修改连接文件权限

    os.lchown(path, uid, gid)

    更改文件所有者,类似 chown,但是不追踪链接。

    os.link(src, dst)

    创建硬链接,名为参数 dst,指向参数 src

    os.listdir(path)

    返回path指定的文件夹包含的文件或文件夹的名字的列表。

    os.lseek(fd, pos, how)

    设置文件描述符 fd当前位置为pos, how方式修改: SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始. 在unix,Windows中有效

    os.lstat(path)

    像stat(),但是没有软链接

    os.major(device)

    从原始的设备号中提取设备major号码 (使用stat中的st_dev或者st_rdev field)。

    os.makedev(major, minor)

    以major和minor设备号组成一个原始设备号

    os.makedirs(path[, mode])

    递归文件夹创建函数。像mkdir(), 但创建的所有intermediate-level文件夹需要包含子文件夹。

    os.minor(device)

    从原始的设备号中提取设备minor号码 (使用stat中的st_dev或者st_rdev field )。

    os.mkdir(path[, mode])

    以数字mode的mode创建一个名为path的文件夹.默认的 mode 是 0777 (八进制)。

    os.mkfifo(path[, mode])

    创建命名管道,mode 为数字,默认为 0666 (八进制)

    os.mknod(filename[, mode=0600, device])

    创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。

    os.open(file, flags[, mode])

    打开一个文件,并且设置需要的打开选项,mode参数是可选的

    os.openpty()

    打开一个新的伪终端对。返回 pty 和 tty的文件描述符。

    os.pathconf(path, name)

    返回相关文件的系统配置信息。

    os.pipe()

    创建一个管道. 返回一对文件描述符(r, w) 分别为读和写

    os.popen(command[, mode[, bufsize]])

    从一个 command 打开一个管道

    os.read(fd, n)

    从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。

    os.readlink(path)

    返回软链接所指向的文件

    os.remove(path)

    删除路径为path的文件。如果path 是一个文件夹,将抛出OSError; 查看下面的rmdir()删除一个 directory。

    os.removedirs(path)

    递归删除目录。

    os.rename(src, dst)

    重命名文件或目录,从 src 到 dst

    os.renames(old, new)

    递归地对目录进行更名,也可以对文件进行更名。

    os.rmdir(path)

    删除path指定的空目录,如果目录非空,则抛出一个OSError异常。

    os.stat(path)

    获取path指定的路径的信息,功能等同于C API中的stat()系统调用。

    os.stat_float_times([newvalue])

    决定stat_result是否以float对象显示时间戳

    os.statvfs(path)

    获取指定路径的文件系统统计信息

    os.symlink(src, dst)

    创建一个软链接

    os.tcgetpgrp(fd)

    返回与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组

    os.tcsetpgrp(fd, pg)

    设置与终端fd(一个由os.open()返回的打开的文件描述符)关联的进程组为pg。

    os.tempnam([dir[, prefix]])

    返回唯一的路径名用于创建临时文件。

    os.tmpfile()

    返回一个打开的模式为(w+b)的文件对象 .这文件对象没有文件夹入口,没有文件描述符,将会自动删除。

    os.tmpnam()

    为创建一个临时文件返回一个唯一的路径

    os.ttyname(fd)

    返回一个字符串,它表示与文件描述符fd 关联的终端设备。如果fd 没有与终端设备关联,则引发一个异常。

    os.unlink(path)

    删除文件路径

    os.utime(path, times)

    返回指定的path文件的访问和修改的时间。

    os.walk(top[, topdown=True[, οnerrοr=None[, followlinks=False]]])

    输出在文件夹中的文件名通过在树中游走,向上或者向下。

    os.write(fd, str)

    写入字符串到文件描述符 fd中. 返回实际写入的字符串长度

    Python中的异常处理

    1.异常类型

    异常名称

    描述

    BaseException

    所有异常的基类

    SystemExit

    解释器请求退出

    KeyboardInterrupt

    用户中断执行(通常是输入^C)

    Exception

    常规错误的基类

    StopIteration

    迭代器没有更多的值

    GeneratorExit

    生成器(generator)发生异常来通知退出

    StandardError

    所有的内建标准异常的基类

    ArithmeticError

    所有数值计算错误的基类

    FloatingPointError

    浮点计算错误

    OverflowError

    数值运算超出最大限制

    ZeroDivisionError

    除(或取模)零 (所有数据类型)

    AssertionError

    断言语句失败

    AttributeError

    对象没有这个属性

    EOFError

    没有内建输入,到达EOF 标记

    EnvironmentError

    操作系统错误的基类

    IOError

    输入/输出操作失败

    OSError

    操作系统错误

    WindowsError

    系统调用失败

    ImportError

    导入模块/对象失败

    LookupError

    无效数据查询的基类

    IndexError

    序列中没有此索引(index)

    KeyError

    映射中没有这个键

    MemoryError

    内存溢出错误(对于Python 解释器不是致命的)

    NameError

    未声明/初始化对象 (没有属性)

    UnboundLocalError

    访问未初始化的本地变量

    ReferenceError

    弱引用(Weak reference)试图访问已经垃圾回收了的对象

    RuntimeError

    一般的运行时错误

    NotImplementedError

    尚未实现的方法

    SyntaxError

    Python 语法错误

    IndentationError

    缩进错误

    TabError

    Tab 和空格混用

    SystemError

    一般的解释器系统错误

    TypeError

    对类型无效的操作

    ValueError

    传入无效的参数

    UnicodeError

    Unicode 相关的错误

    UnicodeDecodeError

    Unicode 解码时的错误

    UnicodeEncodeError

    Unicode 编码时错误

    UnicodeTranslateError

    Unicode 转换时错误

    Warning

    警告的基类

    DeprecationWarning

    关于被弃用的特征的警告

    FutureWarning

    关于构造将来语义会有改变的警告

    OverflowWarning

    旧的关于自动提升为长整型(long)的警告

    PendingDeprecationWarning

    关于特性将会被废弃的警告

    RuntimeWarning

    可疑的运行时行为(runtime behavior)的警告

    SyntaxWarning

    可疑的语法的警告

    UserWarning

    用户代码生成的警告

    2.异常处理

    1)try/except语句

    捕捉异常通常用try(捕捉错误)/except(处理错误)语句。如果你不想在异常发生时结束你的程序,只需在try里捕获它。异常可带参数,用于说明异常原因

    
     
    
     
    
     
    try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") except (IOError,RuntimeError): # 当出现这两种error中的一种时,执行except后面的操作  print("Error: 没有找到文件或读取文件失败") except Exception as e: # 使用异常基类捕获  print("Error: 出错") else: print("内容写入文件成功") fh.close()

     

    2)try/finally语句

    try-finally 语句无论是否发生异常都将执行最后的代码。

    
     
    
     
    try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") finally: print("Error: 没有找到文件或读取文件失败")
    
     
    
     

    3.自己设置异常(用于bug修改、错误检查)

    我们可以使用raise语句自己触发异常

    raise语法格式如下:

    raise [Exception [, args [, traceback]]]

    语句中Exception是异常的类型(例如,NameError)参数是一个异常参数值。该参数是可选的,如果不提供,异常的参数是"None"。

    最后一个参数是可选的(在实践中很少使用),如果存在,是跟踪异常对象。例子如下:

    
     
    
     
    def functionName( level ): if level < 1: raise Exception("Invalid level!", level) # 触发异常后,后面的代码就不会再执行
    
     

    对于自定义的异常,在使用except语句处理异常时,一定要将Exception中的异常名作为except语句的一个参数。例子如下:

    
     
    
     
    try: #正常逻辑 except "Invalid level!": #触发自定义异常 else: #其余代码
     
    
     

    4.自己创建异常类型,用于常见异常复用

    一个异常可以是一个字符串,类或对象。

    
     
    
     
    class Networkerror(RuntimeError): # 基于RuntimeError类创建一个新的类  def __init__(self, arg): # 定义一个函数  self.args = arg
     
    
     
    
     
    
     
    
     
    try: raise Networkerror("Bad hostname") #抛出一个Networkerror异常 except Networkerror as e: #匹配异常的类型,当出现了Networkerror型异常时,执行该except语句,并传递变量e,变量 e 是用于创建Networkerror类的实例,这里的e应该就是这个异常对象?  print(e.args)
     
      
     

    Python内置函数

    内置函数

    abs()

    divmod()

    input()

    open()

    staticmethod()

    all()

    enumerate()

    int()

    ord()

    str()

    any()

    eval()

    isinstance()

    pow()

    sum()

    basestring()

    execfile()

    issubclass()

    print()

    super()

    bin()

    file()

    iter()

    property()

    tuple()

    bool()

    filter()

    len()

    range()

    type()

    bytearray()

    float()

    list()

    raw_input()

    unichr()

    callable()

    format()

    locals()

    reduce()

    unicode()

    chr()

    frozenset()

    long()

    reload()

    vars()

    classmethod()

    getattr()

    map()

    repr()

    xrange()

    cmp()

    globals()

    max()

    reversed()

    zip()

    compile()

    hasattr()

    memoryview()

    round()

    __import__()

    complex()

    hash()

    min()

    set()

    delattr()

    help()

    next()

    setattr()

    dict()

    hex()

    object()

    slice()

    dir()

    id()

    oct()

    sorted()

    exec内置表达式

    Python面向对象

    1.面向对象技术简介

    ·       类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例(对象是类实例化之后的结果)

    ·       类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

    ·       数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。

    ·       方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。

    ·       实例变量:定义在方法中的变量,只作用于当前实例的类。

    ·       继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。

    ·       实例化:创建一个类的实例,类的具体对象

    ·       方法:类中定义的函数

    ·       对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法

    2.创建类

     

    '所有员工的基类'
    class Employee:
        empCount = 0
        def __init__(self, name, salary): #构造函数
            self.name = name            # 添加实例属性
            self.salary = salary        # 添加实例属性
            Employee.empCount += 1      # 修改类属性
        def displayCount(self):         # 添加实例方法
            print("TotalEmployee %d" % Employee.empCount) # 读取类属性
    
        def displayEmployee(self):      # 添加实例方法
            print("Name:", self.name, ", Salary:", self.salary) # 读取实例属性

     

     

     

    ·    empCount变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用 Employee.empCount访问。

    ·       第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法

    ·       self代表类的实例,self在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。Self代表了一件事情,那就是:类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,按照惯例它的名称是 self

    3.创建实例对象

    实例化类其他编程语言中一般用关键字 new,但是在 Python中并没有这个关键字,类的实例化类似函数调用方式。

    以下使用类的名称Employee 来实例化,并通过 __init__ 方法接受参数。

     

    "创建 Employee类的第一个对象"
    emp1 = Employee("Zara",2000)
    "创建 Employee类的第二个对象"
    emp2 = Employee("Manni",5000)
     

     

    4.操作对象属性

    下面是读取对象属性的实例:

     

    '所有员工的基类'
    class Employee:
        empCount = 0
        def __init__(self, name, salary): #构造函数
            self.name = name            # 添加实例属性
            self.salary = salary        # 添加实例属性
            Employee.empCount += 1      # 修改类属性
        def displayCount(self):         # 添加实例方法
            print("TotalEmployee %d" % Employee.empCount) # 读取类属性
    
        def displayEmployee(self):      # 添加实例方法
            print("Name:", self.name, ", Salary:", self.salary) # 读取实例属性
    
    
    # "创建 Employee 类的第一个对象"
    emp1 =Employee("Zara",2000)
    # "创建 Employee 类的第二个对象"
    emp2 =Employee("Manni",5000)
    emp1.displayEmployee()
    emp2.displayEmployee()
    print("TotalEmployee %d" %Employee.empCount)

     

     

     

     

     

    以下函数还可以对属性进行读取之外的操作:

    ·       getattr(obj,name[, default]) :访问对象的属性。

    ·       hasattr(obj,name):检查是否存在一个属性。

    ·       setattr(obj,name,value):设置一个属性。如果属性不存在,会创建一个新属性。

    ·       delattr(obj,name) :删除属性。

    5.Python内置的类属性

    ·       __dict__ :类的属性(包含一个字典,由类的数据属性组成)

    ·       __doc__ :类的文档字符串

    ·       __name__:类名

    ·       __module__:类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)

    ·       __bases__ :类的所有父类构成元素(包含了一个由所有父类组成的元组)

    6.类的继承

    面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。继承完全可以理解成类之间的类型和子类型关系

    在python中继承中的一些特点:

    ·       1:在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用

    ·       2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数

    ·       3:Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。

    如果在继承元组中列了一个以上的类,那么它就被称作"多重继承" 。

     

    class Parent:
        # 定义父类
        parentAttr =100
        def __init__(self):
            print("调用父类构造函数")
        def parentMethod(self):
            print('调用父类方法')
        def setAttr(self,attr):
            Parent.parentAttr =attr
        def getAttr(self):
            print("父类属性 :",Parent.parentAttr)
     
    class Child(Parent):
        # 定义子类
        def __init__(self):
            print("调用子类构造方法")  #无论子类还是父类,都要单独写一次_init_
        def childMethod(self):
            print('调用子类方法')
        def getAttr (self):
            print('重写父类方法,因为父类方法不能满足需求')
    
    c = Child()  #实例化子类
    c.childMethod()#调用子类的方法
    c.parentMethod()#调用父类方法
    c.setAttr(200)  #再次调用父类的方法 -设置属性值
    c.getAttr()#再次调用父类的方法 -获取属性值

     

     

     

    你可以使用issubclass()或者isinstance()方法来检测,一个类或对象是否为其他类或对象的子类。

    ·       issubclass() -布尔函数判断一个类是另一个类的子类或者子孙类,语法:issubclass(sub,sup)

    ·       isinstance(obj, Class)布尔函数如果objClass类的实例对象或者是一个Class子类的实例对象则返回true

    7.运算符重载

    Python同样支持运算符重载,实例如下:

     

    class Vector:
        def __init__(self, a, b):
            self.a = a
            self.b = b
        def __str__(self):
            return 'Vector(%d, %d)' % (self.a, self.b)
        def __add__(self, other):
            return Vector(self.a + other.a, self.b + other.b)
            
    
    
    v1 = Vector(2, 10)
    v2 = Vector(5, -2)
    print(v1 + v2)

     

     

     

    以上代码执行结果如下所示:

     

    Vector(7, 8)

     

     

     

     

     

    8.类的私有属性及方法

    1)类的私有属性

    __private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用是self.__private_attrs

    2)类的私有方法

    __private_method:两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用self.__private_methods

    3)实例

     

    class JustCounter:
        __secretCount = 0
        # 私有变量
        publicCount = 0
        # 公开变量
        def count(self):
            self.__secretCount += 1
            self.publicCount += 1
            print(self.__secretCount)  # 在内部使用私有化属性,不会产生错误
    
    counter = JustCounter()
    counter.count()
    counter.count()
    print(counter.publicCount)
    print(counter.__secretCount)
    # 报错,实例不能访问私有变量

     

     

     

     

     

    9.单下划线、双下划线、头尾双下划线说明:

    ·       __foo__:定义的是特列方法,类似 __init__() 之类的。

    ·       _foo:以单下划线开头的表示的是 protected类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *

    ·       __foo:双下划线的表示的是私有类型(private)的变量,只能是允许这个类本身进行访问了

     

    展开全文
  • Python学习教程Python学习路线_Python学习教程):新手入门Python必须要知道的这19个语法 学Python必须要知道要了解的19个基础语法,你准备好了吗? 解释型语言,无需编译即可运行 提供了交互式命令行 基于对象的...

    Python学习教程(Python学习路线_Python学习教程):新手入门Python必须要知道的这19个语法

    学Python必须要知道要了解的19个基础语法,你准备好了吗?

    • 解释型语言,无需编译即可运行
    • 提供了交互式命令行
    • 基于对象的编程思想
    • 跨平台和良好的兼容性,在Windows、Mac、Linux上都可运行
    • 简单好用而且功能强大

    01 中文编码
    很多同学在打开数据时会遇上乱码问题,其原因是字符集的编码问题。Linux和Mac默认的编码集是UTF8,而Windows则是ASCII。

    如果数据编码的字符集,和你使用Python进行处理时所用的字符集不同,则会出现乱码问题。

    另外,我个人的习惯是在Python代码的头部加入以下内容,其中第二行声明了使用UTF8字符集。

    #!/usr/bin/env python# coding:utf8
    

    02 变量
    Python中的变量可以看作是一个个容器,里面存放着我们需要使用到的值。

    Python对变量名的要求和其他语言一样:可以包括英文、数字以及下划线,但不能以数字开头,区分大小写。当然我推荐,

    变量名用纯英文就很好,并且取一些有意义的名称,便于自己理解每个变量的作用。

    Python是一门弱类型的语言,在使用变量时无需声明其类型。Python中的变量包括以下几类:数值、字符串、列表、元组、字典。

    03 数值

    数值包括整型和浮点型,分别对应整数和浮点数,后者精度更高。

    #整型a = 1# 浮点型b = 2.1print a, b
    

    04 字符串
    字符串也就是我们经常接触到的文本,可以往里面放任意长度的内容,用单引号或双引号括起来。应当注意,

    中文以及中文符号只能出现在字符串內,如果在下面第三行中使用了中文输入法的逗号 ,Python将报错。

    c =  Hello d =  你好 print c, d
    

    使用 + 可以拼接两个字符串。

    print c + d
    

    使用 len() 可以得到字符串的长度。

    print len( Hello World )
    

    使用切片可以访问字符串中的某个字符或某个片段。

    #位置下标从0开始c =  Hello World # 打印结果为H,下标为0表示第一个字符print c[0]
    #打印结果为d,下标为负数表示从后往前数# 所以-1表示倒数第一个字符print c[-1]
    #使用:返回一个片段,冒号前后分别为开始下标和结束下标# 包括开始下标,但不包括结束下标
    #因此c[1:5]表示,返回下标从1到4的片段,即第二个到第五个字符print c[1:5]
    #冒号前后的下标同样可以使用负数
    #或者不提供,表示从最左端开始或一直到最右端print c[1:-1], c[:5], c[3:]
    

    05 列表

    列表好比一条队伍,里面依次存放着多个变量。列表和字符串类似,但字符串中的每个元素都是字符,

    而列表中的每个元素可以是任意类型的变量。

    #使用[]定义一个空列表,使用append()向列表尾部添加一个元素
    #如果要添加到首部,就用prepend()好了a = []a.append(1)a.append(2.1)a.append( Hello )print a
    

    使用 len() 可以获得列表的长度。

    print len(a)
    

    列表元素的按下标访问和赋值等操作,和字符串都是类似的。

    print a[1], a[-1]a[1] = 100print a
    

    使用 del 删除列表中的某个元素。

    del a[0]print a
    

    06 元组
    元组和列表类似,唯一的不同是元组中的元素在初始化之后不能再更改,因此可以理解成一个只读的变量。

    #使用()定义一个元组a = (1, 2.1,  Hello )# 尝试修改元组中的元素会报错a[0] = 100
    

    07 字典

    字典是一种极为重要的变量类型,使用一个key来访问相应的value,即一种键值对的数据形式。

    #使用{}定义一个字典a = {}# 使用key来赋值valuea[ k1 ] = 1a[ k2 ] = 2.1a[ k3 ] =  Hello
    

    所以能够总结出字典和列表的不同。列表中的元素是有序对等的,所以是用下标来赋值和访问,而字典中的元素是无序的,

    所以是用key来操作相应value。

    #也可以在定义字典和列表的同时进行赋值li = [1, 2.1,  Hello ]di = { k1 : 1,  k2 : 2.1,  k3 :  Hello }
    

    使用 has_key() 判断字典中是否有某个key。

    print di.has_key( k4 )
    

    如果访问不存在的key,Python将会报错。在赋值的时候,如果key已经存在,则会用新的value覆盖已有的value。

    08 注释
    被注释的代码将不会运行,可以看作是写给自己和其他程序猿阅读的一些笔记和说明,提高代码可读性。

    #这里是单行注释 这里是很多行注释
    在Sublime中,选中需要注释的内容,按Ctrl+/即可完成注释。

    09 保留字符
    在Python中,有一些字符串具有某些特定功能,如 import 、 class 等。我们在选择变量名时,应注意避开这些保留字符。

    #以下变量赋值将报错import = 1
    

    10 .行和缩进
    在Python中,代码块的边界不是通过大括号等符号进行显式划分,而是通过行的缩进实现的。

    连续相同缩进水平的代码处于同一个代码块,在使用 for 、 while 、 if 、 try 等语法时需要注意每行代码的缩进。

    11 运算符
    运算符的作用是根据已有的变量生成新的变量,主要有以下几种:

    算术运算符:+,-,*,/,%,即加、减、乘、除、取余

    比较运算符:==,!=,>,<,>=,<=,即等于、不等于、大于、小于、大于等于、小于等于

    赋值运算符:=,+=,-=,*=,/=,%=,即赋值、加赋值、减赋值、乘赋值、除赋值、取余赋值

    逻辑运算符:and,or,not,即与、或、非

    a = 1b = 2print a + bprint a == b# 等价于 a = a + 3a += 3print ac = Trued = Falseprint c and d
    

    12 条件
    在写代码的时候,往往需要根据某些条件进行判断,并根据判断结果执行不同的分支代码。

    a = 1# 单个条件if a == 1:    print 11111# 处理条件不成立的分支if 
    a == 2:    print 22222else:    print 33333# 多个条件,加多少个都可以if 
    a == 1:    print 11111elif a == 2:    print 22222else:    print 33333
    

    需要注意的是,但凡出现了 if 和 elif ,就需要加上相应的条件判断,并且注意代码的缩进。

    在Sublime中输入 if 会出现相应的提示,可以方便地补全代码,在换行时光标也会自动跳到合适的缩进处。

    13 循环
    如果需要打印从1到100的100个数,肯定不会傻傻地写100行print代码,而是会用循环来处理类似的重复性工作。

    14 while 循环
    while 循环的思想是,只要某一条件成立,就不断执行循环体里的代码,直到条件不再成立。

    flag = 1while flag < 10:    print flag    
    
    #一定要记得在循环体里修改条件变量    
    #否则可能导致死循环    flag += 1
    

    15 for 循环

    for 循环的循环次数一般是事先预知的,将一个标志变量从某个起始值迭代到某个终止值后即结束。

    #x从0开始,一直到9结束for x in xrange(0, 10):    print x
    

    可以用 for 循环方便地遍历列表和字典。

    li = [1, 2.1,  Hello ]dict = { k1 : 1,  k2 : 2.1,  k3 :  Hello }
    #遍历列表,这里的item只是一个临时变量,取别的名称也行for item in li:    print item
    #遍历字典的全部key,这里的key也只是一个临时变量,名称不重要for key in dict.keys():    print key
    #遍历字典的全部value,这里的value也只是一个临时变量,名称不重要for value in dict.values():    print value# 同时遍历key和valuefor key, value in dict.items():    print key, value
    

    16 循环控制

    循环控制主要包括三种: pass 、 continue 、 break 。

    pass 表示什么也不做,只是占一行代码的位置;continue 表示立即退出本轮循环,继续执行后续轮循环;

    break 表示立即推出循环,后续循环也不再执行。

    for x in xrange(0, 10):    if x == 5:        pass    else:        print xfor x in xrange(0, 10):    if x == 5:        continue    print xfor x in xrange(0, 10):    if x == 5:        break    print x
    

    17 时间

    在处理数据时,很多地方都会涉及到时间,例如数据产生的时间。先介绍一下时间戳的概念,

    时间戳指的是从1970年1月1日0时0分0秒开始,到某一时刻所经历的秒数,可以是整数或者小数,后者的精度更高。

    为什么需要时间戳这样的一个概念?因为对于同一个时刻,不同人的描述可能不同,毕竟文本的形式千变万化,

    而时间戳使得时间的表达得到了统一,每个时刻只能用唯一的整数或浮点数来表示,同时也便于计算时间差这样的处理。

    #来看一下当前时刻的时间戳吧import timet = time.time()print t, type(t)
    

    关于时间戳,最常用的处理便是时间戳和时间文本之间的转换,例如将 2016年10月1日 10时0分0秒 转为时间戳。

    import time# 时间文本转时间戳,精确到秒a =  2016-10-01 10:00:00 a = int(time.mktime(time.strptime(a, %Y-%m-%d %H:%M:%S )))print a# 时间戳转时间文本b = int(time.time())b = time.strftime( %Y-%m-%d %H:%M:%S , time.localtime(b))print b
    

    其中, %Y 、 %m 等都是时间字段,前者表示四位的年份,后者表示两位的月份。

    文件
    文件操作包括向文件中写内容,以及从文件中读内容,使用 open() 打开一个文件。

    #写文件# 重新写模式,打开文件时会将文件内容清空fw = open( data.txt ,  w )# 追加写模式,打开文件后保留原始内容,继续写入for x in xrange(0, 10):    # 将整数转成文本再写入    fw.write(str(x))    # 也可以每次写入之后换行,
    
    为转义字符,表示换行    # fw.write(str(x) +  
     )fw.close()# 读文件fr = open( data.txt ,  r )# 一行一行地读,line只是个临时变量,取别的名称也行for line in fr:    print line    # 如果每行后面有换行,可以将换行符去掉,使内容更紧凑    # strip()可以去掉字符串两端的空白字符    # print line.strip()fr.close()
    

    18 异常
    Python代码中可能会出现一些可以预知的问题,例如字典访问的key不存在。
    如果不加处理,发生问题的时候Python便会报错并退出,可能之前跑了很久又要重头再来。

    因此,我们需要对可能出现的异常进行捕捉和处理。异常的结构由 try 、 except 、 else 、 finally 四部分组成。

    try:    # 尝试执行这些代码    print 1 / 0except Exception, e:    # 如果出现异常就进行处理    # e为出现的异常类型    print eelse:    # try里的代码没有出错    # 可以执行后续工作了    print  没有出错 finally:    # 无论是否出错,都会执行的代码    print  一定会执行
    

    19 函数

    函数的作用是代码模块化,将可重用的代码封装成一个函数,这样在需要使用的时候就只需调用写好的函数即可,而不用重新写一遍代码。

    函数的使用包括两个部分,函数的定义和函数的调用。除此之外,函数可以有一个或多个参数,参数之间以逗号分开,

    为函数的功能提供更多的灵活性。

    #定义函数def hello(name1, name2):    print  Hello   + name1 +     + name2# 调用函数hello( Python ,  JavaScript )
    

    ——文章参考自公众号小詹学Python

    展开全文
  • 百度上一搜python跳一跳关键词,就弹出不知多少相关教程。但我发现很多代码用的方法似乎有一定缺陷,在遇到一些情况时就无法起作用了。而这些情况在游戏过程中不可避免的会出现,这就导致最终的分数可能并不会很高...

    前言

    本篇博客介绍了如何使用python代码玩微信跳一跳游戏。很早之前就听说过使用python脚本玩跳一跳游戏刷分,当时对相关原理一窍不通,但这完全不影响我的好奇心和求知欲。如今终于有机会探求其中的奥妙。

    百度上一搜python、跳一跳关键词,就弹出不知多少相关教程。但我发现很多代码用的方法似乎有一定缺陷,在遇到一些情况时就无法起作用了。而这些情况在游戏过程中不可避免的会出现,这就导致最终的分数可能并不会很高。

    本篇博客综合多方面的idea,主要参考此源码(下提到此源码一词,即指代此处),基于自己的理解做了一些修改和简化。原文中分别给出了在 Android 和 iOS 下运行的代码,和多种不同思路的方法。此处仅介绍Android下的一种方法。


    环境配置要求

    1. 安装python3

    2. 安装ADB,并设置好环境变量,确保在CMD中adb命令可识别。安装完后插入安卓设备,且打开USB调试模式,在终端中输入: adb devices. 显示类似如下表明设备已连接

    List of devices attached
    6934dc33 device
    
    1. 安装其他依赖库:opencv, numpy

    代码实现

    分析

    1. 在本项目中,adb工具的作用是将游戏截图发送到电脑端、模拟手指按压使棋子跳跃。adb工具的使用在本项目中不起关键作用,即使不了解adb工具也可完成本项目。(博主就完全不了解adb命令)
    2. 电脑依据游戏截图,识别棋子所处位置和下一步落点中心位置(称棋盘),计算两者距离,再计算按压时间。最后执行相应的adb命令,手机端棋子即会进行跳跃。

    显然,本项目的关键点有三个:

    1. 识别棋子所处位置
    2. 识别棋盘中心位置
    3. 计算按压时间

    识别棋子所处位置

    我使用的方法是利用opencv中的模板匹配函数cv2.matchTemlpate(),只需要提供一张棋子的图像即可,准确度非常高。左一图为棋子图像,左二图为识别结果。

    棋子识别

    棋子位置已经有了,但我们要的是棋子所处的坐标点。取方框X方向的中点为X坐标,取方框Y方向 9/10 处为Y坐标。棋子所处的坐标点就是(X, Y),如右一图。

    识别棋盘中心位置

    这部分比较复杂,我参照了此源码的实现方法,但二者又有明显不同。

    据观察,我们认为,在Y方向上(竖直方向)棋盘出现的位置在1/3 - 2/3处之间。而在X方向上(水平方向),如果棋子在屏幕偏左方,棋盘必在棋子的右方;如果棋子在屏幕偏右方,棋盘必在棋子的左方。那么我们搜索的范围就大大缩小,如下图红框(此时棋子在屏幕偏左方):

    棋盘可能的位置

    寻找上顶点

    我们先找到棋盘的上顶点。

    显然,棋盘上顶点颜色与背景色差异较大,可依据这一特点在区域内搜索。从红框左上角像素开始逐行搜索,取每行最左端点为初始点记录像素值,与该行内的每个像素进行比对,如果二者差异较大,就认为找到了上顶点。

    为提高搜索速度,可以每50行取一行搜索,如果出现差异较大的点,在重新搜索这50行,取第一个差异点为上顶点。

    这种方法在棋盘是菱形时是有效的,但棋盘是椭圆形时是否有效呢?你可能认为也有效,因为椭圆形也只具有一个上顶点。实际上,我发现椭圆形棋盘在截图中没有上顶点,最上面是一条短线(把截图放大也能发现)。因此,在用上面的方法时,得到的上顶点会是这条短线的最左端的点。

    椭圆形棋盘的上端短线

    上面的方法是,在行内找到一个差异点就终止搜索,认为这个差异点是上顶点。我们修改一下,在行内找差异点后继续搜索该行,并记录差异点,知道该行搜索完毕终止搜索。把记录的所有差异点的取平均值,就能得到短线的中点,即椭圆的上顶点。

    寻找中心点

    好了,我们找到棋盘的上顶点了,无论它是椭圆形还是菱形,结果都是准确的。

    但如何寻找棋盘的中心点?我也不知道。起初我的想法是,找到棋盘的上顶点和右端点,二者分别做个辅助线交点就是棋盘中心点了。于是我用类似寻找上顶点的方法,寻找右端点,从右向左逐列搜索,没错是找到了。但我发现,少部分情况下会出问题。当棋盘位于屏幕偏右方,结果完全准确;当棋盘位于屏幕偏左方,因为我们限制了搜索范围(只搜索棋子的左方),结果大部分情况下也是准确的。什么时候不准确呢?当棋子和棋盘靠的很近,而棋盘又比较大的时候,棋盘的右端点被棋子遮住了…这我还搜索个啥?虽然这种情况很少出现,但不得不说他不是种好方法。

    假装有图,实际上玩了半天游戏没找到好的示意图

    那搜索棋盘左端点行不行?也不行。当棋盘位于屏幕偏右方,棋盘左端点也有被遮住的可能。

    这个时候,此源码使用的方法就比较高端,出现上述情况时也能准确计算出中心点。下面我讲解一下。

    得到了棋盘的上顶点坐标,它的X坐标就是棋盘中心点的X坐标,那么只要计算出Y坐标。我理解这位牛人的意思应该是,游戏有一个对称中心,并且该对称中心到棋盘中心的连线与水平方向的夹角是固定的。你可能认为对称中心是屏幕的中点,但这位牛人是这样计算的:

    center_x = w / 2 + (24 / screen_width) * w
    center_y = h / 2 + (17 / screen_height) * h
    

    给出的角度是tan θ = 25.5 / 43.5 。

    咋来的?不知道,真不知道。算了,先用吧。

    既然知道了这个规律,那么我们就可以这样计算出棋盘中心点的坐标(X, Y ):

    在这里插入图片描述
    这种规律到底是不是存在的?我们可以验证一下,下面是我调试代码时得到的一些图像:

    调试代码得到的图像

    仅用肉眼来看的话,我们几乎可以认为两个棋盘中心点的连线是平行的(此时棋子处于中心点)。而大量事实也证明了,牛人给出的规律是有效的,计算出的中心点位置很准确。

    计算按压时间

    好了,我们终于得到了棋子起始坐标点、棋盘中心点坐标,那么就可以计算出二者的直线距离了。然后根据直线距离,计算按压时间。

    说实话,这位大牛计算按压时间的代码,我实在没看懂…不过我猜测,也许是考虑不同手机屏幕分辨率适配等等问题。大家有兴趣可以看一下。

    我就比较粗暴,勾股定理计算直线距离,直线距离乘以时间系数等于按压时间(我这种方法的效果似乎也不差)。这里的时间系数,是大牛源码里提到的。似乎是不同屏幕大小的手机时间系数略有不同,此源码里已经给了配置文件,我也在我的源码里放了,略微做了些修改。


    最终效果

    最终效果比较依赖于配置文件中的数据,尤其是按压时间系数,大家可以根据自己的实际情况进行修改。

    我的手机是Huawei nova 2s,屏幕大小是2160x1080,实际分数随随便便能够达到三四千分,最后一次游戏的分数是8000多分。欢迎大家在评论区晒出自己的分数哦!

    游戏分数

    源码奉上

    GitHub


    使用说明

    1. 安卓手机通过数据线与电脑相连,打开手机的USB调试
    2. 电脑端执行adb devices,确保手机已连接
    3. config 文件夹下有对应于手机分辨率的配置文件。可以将config.json文件复制到项目根目录下,代码会优先读取;也可不复制,代码自动在config文件夹下搜索匹配的配置文件;实际效果不好时,可手动调整配置文件。
    4. 手机界面切换到微信跳一跳游戏,点击开始游戏
    5. 执行python wechat_jump_auto.py

    总结

    特别鸣谢这位大牛,没有ta本篇博客无法顺利完成。本篇博客是博主基于自身理解写成,难免出现错误,望各位批评指正。无论是建议、想法和疑问,各位皆可在评论区提出,集思广益,互帮互助。

    欢迎访问我的个人博客

    展开全文
  • 感谢廖老师精彩的Python教程,收益良多,感谢感谢! 整理笔记,以备后续复习,第部分一直到模块结束,整理如下,其中大量的单引号是有问题的,由于word直接打的,嫌麻烦,没有都进行修正,请见谅 1、a = ‘XYZ.....
  • 现在你要做的第件事是构建Hello World模块并在Python中自己尝试。在本节中,我们将概述实现这目标所需的步骤。我们将使用与每个boost发行版捆绑在一起的构建工具:bjam。 注意 建筑没有bjam 除了...
  • 本文持续更新… 我的目录说明1 字符串,string1.1 字符串大小写1.2 合并字符串1.2 空白1.3 删除空白1.4 转义字符2 数学运算符注释 说明 本博文作为笔者笔记使用,不会很全面 1 字符串,string ...
  • 分支结构的应用场景迄今为止,我们写的Python代码都是一条一条语句顺序执行,这种结构的代码我们称之为顺序结构。然而仅有顺序结构并不能解决所有的问题,比如我们设计一个游戏,游戏第一关的通关条件是玩家获得1000...
  • 大体步骤: 1.安装python运行环境及各种插件 2.使用adb驱动连接到手机调试 ...因为自动玩跳一跳的程序是用Python语言写的,所以我们需要安装python运行环境。 这里需要python3以及python的matplotlib和
  • 在这篇Python教程中,你将会学到计算机编程的基础知识,使用对新手来说最棒的编程语言之。 什么是编程? 尽可能简单的讲,编程是编写代码,命令计算机去完成某项任务的艺术。这里讲的某项任务
  • Python教程 - Django

    2019-04-04 01:09:30
    Python教程 - DjangoDjango 系统环境搭建后台流程创建第个Django程序PyCharm启动路由系统 - urls2. 正常映射3.URL 中带参数映射4. URL在APP中处理5. URL中嵌套参数6. 传递额外的参数7.URL的反向解析 reverseVIEWS ...
  • 第1部分:Python 基础教程 1、Hello/编码  Python2.x中默认的编码格式是 ASCII 格式,在没修改编码格式时无法正确打印汉字,所以在读取中文时会报错。  解决方法为只要在文件开头加入 # -*- coding: UTF-8 -*- ...
  • python进阶教程

    2018-07-23 11:16:50
    Python进阶中文教程 转自GitBookhttps://eastlakeside.gitbooks.io/interpy-zh/content/?q= 我仔细学习了该进阶教程,原著根据《Intermediate Python》译注,学习了之后我再例子以及重点地方多做了一些...
  • 实现思路: 调用adb命令,截图 寻找小小人的底部中心点role(从下到上扫描,直到找到小小人相同像素的点,至于小小人像素点rgb是什么,可以使用photoshop查看) 寻找棋盘最高点top,然后寻找棋盘最右点。...
  • 迄今为止,我们写的Python代码都是一条一条语句顺序执行,这种结构的代码我们称之为顺序结构。然而仅有顺序结构并不能解决所有的问题,比如我们设计一个游戏,游戏第一关的通关条件是玩家获得1000分,那么在完成本局...
  • 所谓函数,就是把 具有独立功能的代码块 组织为个小模块,在需要的时候 调用 函数的使用包含两个步骤: 定义函数 —— 封装 独立的功能 调用函数 —— 享受 封装 的成果 函数的作用,在开发程序时,使用函数...
  • Python爬虫入门项目

    2019-09-21 00:02:43
    Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的个编程语言。 创始人Guido van Rossum是BBC出品英剧Monty Python’s Flying Circus(中文:蒙提·派森的飞行马戏团)的...
  • 本文通过图文并茂的形式给大家介绍PyCharm第次安装及使用教程,分步骤通过实际案例给大家操作演示,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 pycharm简介 PyCharm是Python IDE...
  • Python Django学习教程

    2015-04-20 14:27:40
    -----------------因为所有教程均有Python、Django、项目安装等, 在此不再赘述------------------- -----------------如果转载请注明出处, 如有错误请指出, 谢谢------------------ 1.创建个项目
1 2 3 4 5 ... 20
收藏数 7,335
精华内容 2,934