美文网首页
Life is short, you need Python!

Life is short, you need Python!

作者: 罗立青 | 来源:发表于2017-04-13 20:23 被阅读0次

    初识Python

    第一次听说Python已经是三四年前的事情了。当时是用C#帮人处理了一个有向图的小代码。对方问,用什么写的,是Python嘛。我才知道还有Python这么个东西。当时只知道这是一个跨平台的脚本语言。随后曾在回家的火车上看过一点点,但一直没有实实在在的使用过。天生的对脚本语言不感兴趣。

    用上Python

    最近在帮助一个朋友搞输入法的算法,需要在Python上进行算法测试。同时,也想着,以后尽量把科学计算的工具从原来可能只有我才用的C#转到比较通用的Python上。于是,匆匆忙忙的看了几天就直接上手了。用了一个多月,感叹Python确实在某些方面是很神奇的。比如,Python可以用a, b = b, a来交换a和b的值。

    实用的数据结构

    应该是因为功能定位不同,Python和其他语言的大部分教程不同。Python一上来并不是讲int、float、double、string和数组等基本类型,而是介绍list,turple和dictionary(还有一个可能不太常用的set结构)这些数据结构。在c#中,list要用ArrayList,turple相当于结构体,dictionary相当于HashTable,三个都已经算是相对高级的应用了,至少是需要增加Using才能使用的(结构体不是)。尤其是字典类型,如果不是万不得以,好像基本不会使用HashTable,更别说的字典中套字典了。而在Python中,不仅把这个三种实用的数据结构做为基础直接使用,而且还经常联合使用。对于纯粹的数据处理和计算来说,大缩短了代码编写的时间。能灵活熟悉的使用这三种数据结构,Python就基本上算是初步掌握了。

    有趣的下标引用

    list,turple和dictionary都是数据的存储结构。引用一串数据中的某一个或某几个是最常用操作。和C#一样,Python也是用[n]来引用,但在操作上Python有许多独特的逻辑。比如,Python的引用是可以用负数的。

    data = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
    data[0]     #取第一个元素,结果为['Monday']
    data[-1]    #取最后一个元素,结果为['Sunday']
    data[:5]    #从开头取,取到5号个元素之前,结果为['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
    data[4:]    #从第4个元素取到最后,结果为['Friday', 'Saturday', 'Sunday']
    data[1:2]   #从第1号元素取,取到2号元素之前,结果为['Tuesday']    
    data[3:-2]  #从3号元素取,取到倒数第2个元素之前,结果为['Thursday', 'Friday']
    

    甚至你还可以这样把所有奇数位或偶数位的取出来,生成一个新的list:

    data[::2]   #结果为['Monday', 'Wednesday', 'Friday', 'Sunday']
    data[1::2]  #结果为['Tuesday', 'Thursday', 'Saturday']
    

    虽然C#也可以用Substring方法实现字符串的截取,但使用上就不如Python来的直观,而且该方法也仅限到普通的字符串。

    独特循环方式

    Python中的循环全是类似于C#中foreach的遍历式循环,如遍历链表、元组或字典。

    for item in data_list:
        print(item)
    for item in data_turple:
        print(item)
    for key in data_dic:
        print(key, data_dic[key])
    

    当然,对于字典类型的普遍,由于很多时候会可能会改变字典的内容,如删除某些键值,所以通常是遍历字典键的链表:

    for key in list(data_dic.keys()):
        ...
    

    那么,如果确实是要计算一个从1加到100的循环又该怎么办呢。在Python中,需要用range内嵌构建一个链表来实现:

    for item in range(1,101):
        ...
    

    所以,Python中通常不会使用i, j, k这种循环变量名。

    Python的循环还能使用一个特别的zip组合,可以把两个链表组合成一个元组的链表,然后把元组中的元素分别赋值给不同的变量进行遍历。至于有什么用,那就要看具体的需求了。在保存输入法的词库数据时,为了节省空间,把同一个拼音的重码和对应的权重保存在了同一条记录中,并用‘|’进行了分隔。那么,获取某一个词的概率,或者是某一个音对应所有词的权重就可以这样写:

    #比如,取出的youji对应的重码概率保存在了result中
    result = '邮寄|0.3|有机|0.2|游击|0.2|游记|0.1'
    result_list = result.split('|') #将结果转为list结构
    for word, weight in zip(result_list[::2], result_list[1::2]):
        print(word, weight) 
    

    zip实际上是先把两个list打包成了一个成员是元组的list,然后再遍历元组,分别把元组的元素赋值给word和weight。如果用C#,就等同于:

    for(i=0;i<=result_list.count-1;i++){
      word = result[i];
      weight = result[i+1];
      i++;
      Console.writeline(word.tostring() + weight.tostring());
    }
    

    虽然看上去好像也不是特别麻烦,但逻辑上还是Python的更易懂一些。

    看不明白的排序

    排序是最常用的算法之一,大部分语言也都内置了排序的方法或函数。但是,主要都是针对基本类型的。如果要对一个结构体,或者类进行排序,其代码量也不算少。比如,前段时间在处理词频信息时,需要按词频进行排序。如果用两个链表分别保存「词」和「频度」,那在对「频度」时,就不能同步调整「词」的顺序。因此,必须把「词」和「频度」放在一个结构体中,对结构体进行排序。在C#中可以这样实现:

    //先需要声明一个结构体,把所有需要同时排序的元素放在一起
    //类似于Python形成一个元组
    struct Unite{
      string word;
      int count;
    }
    //还需要声明一个排序比较的方法,比较的元素类型为声明的结构体
    //在方法中明确排序时的比较元素,及是正序还是逆序
    private static int CompareByCountDes(Unite x, Unite y){
      if (y.m_count - x.m_count > 0) return 1;
      else if (y.m_count - x.m_count < 0) return -1;
      else return string.Compare(x.m_word, y.m_word);
    }
    //然后才能用Sort方法对结构体进行排序
    //Unite_List是一个元素为结构体Unite的链表,即List
    Unite_List.Sort(CompareByCountDes); 
    

    然而,在Python中,对于元素是元组的链表,其排序用一行代码就可以完成:

    sorted(Unite_List, key=lambda item:float(item[1]), reverse=True)
    

    其中,Unite_List中的元素为(word, count)形式的元组,key后面指定的是排序的依据元素,lambda是一个内嵌的小函数(到现在也不是特别明白)。但至少明白,是按item[1]进行排序,即按count进行排序,如果要按word排序,可指定为item[0]。最后的参数reverse如果为「真」,则为逆序,默认值为假,是正序。

    虽然,排序的内部过程大概都是要走两层循环,但在代码上Python则更容易一些。

    简单的文件和数据操作

    把运算的数据保存在文件和数据库,或者从文件或数据库中读取数据,也是常见的操作。C#中读取文本文件,需要声明一个FileStream用来指定文件路径和打开方式,即「读」或「写」或「追加」等。然后,使用StreamReader读取文件。读取的过程一般通过while循环来完成。文件读写之后,还建议对这两个对象执行Close操作。

    但Python中,只需要指定一个文件读取变量就行:

    FileRead = open('read.txt', 'r', encoding='utf-8')
    content = FileRead.readlines()
    for line in content:
        print(line)
    FileRead.close()
    

    如果使用with结构,还可以把close省略掉。

    对于数据库,也可以省掉open和close的过程,也不用像C#那样去声明一个Connection和Command对象。对于sqlite这种轻型的数据库,只需要提供数据库文件的路径,就可以直接执行sql语句:

    conn = sqlite3.connect("sqlite.db")
    conn.execute('create table ...')
    conn.execute('insert into ...')
    conn.execute('delete from ...')
    conn.execute('update ...')
    # 对于查询结果,可以通过遍历的形式读取
    result = conn.execute('select id, name from people')
    for row in result:  #遍历查询结果的第一条记录
        print(row[0], row[1])   #row[0]对应id,row[1]对应name
    

    当然,Python主要用于实现数据处理,所以Python一般多用在后台,前端的UI处理还需要借助其他工具。

    相关文章

      网友评论

          本文标题:Life is short, you need Python!

          本文链接:https://www.haomeiwen.com/subject/ankiattx.html