zoukankan      html  css  js  c++  java
  • 如何优雅的写好python代码?

    Python与其他语言(比如 java或者 C ++ )相比有较大的区别,其中最大的特点就是非常简洁,如果按照其他语言的思路老师写Python代码,则会使得代码繁琐复杂,并且容易出现bug,在Python中,有个词很火,Pythonic。有的同学可能不明白这个词的意义,小编的理解就是有Python的写法写代码,而非是其他语言的通用写法,写出python的特点,写出Ppython的风格。

    下面,就通过几个示例来看看一下不同思维的Python代码的差异。

    1、变量值的交换

    这个词最常见,大家从最开始写java及C++等语言代码都会遇到这个问题,通过一个临时变量来实现的“:

    tmp = a
    a = b
    b = tmp

    而Python中可以之间交换两个变量,即:

    a, b = b, a

    2、列表推导式

    列表推导式是java及C++等语言没有的特性,能够很简洁的实现for循环,可以应用列表,集合或者子字典。

    例如我们要求20以内的整除3的数的平方的列表,可以用如下代码实现:

    numbers = []
    for x in xrange(20):
        if x % 3 == 0:
            numbers.append(x*x)

    而通过列表推导式一行代码就可以实现:

    numbers = [x*x for x in xrange(20) if x % 3 == 0]

    列表推导式可以用于集合和字典,将[...] 变为[...]。集合和字典的实现如下所示:

    集合:

    numbers = {x*x for x in range(0, 20) if x % 3 == 0}

    字典:

    numbers = {x: x*x for x in range(0, 20) if x % 3 == 0}

    3、字符串拼接

    这是一个老生常谈的问题,当我们需要将数个字符串拼接起来的时候,习惯性的使用 “+” 作为连接字符串的手段。

    然而,由于像字符串这种不可变对象在内存中生成后无法修改,合并后的字符串会重新开辟一块内存空间来存储。因此没合并一次就会单独开辟一块内存空间,这样会占用大量的内存,严重影响代码的效率.

    words =['I', ' ', 'LOVE', ' ', 'pYTHON', '.']
    
    sentence = ''
    for word in words:
        sentence += '' + word

    解决这个问题的办法是使用字符串连接的join,Python写法如下:

    words = ['i', ' ', 'love', 'python','']
    
    sentence = ''.join(words)

    4.如何快速翻转字符串

    java 或者 C++ 等语言的写法是新建一个字符串,从最后开始访问员字符串:

    a = 'I love python.'
    
    reverse_a = ''
    for i in range(0, len(a)):
        reverse_a += a[len(a) - i - 1]

    而Python则将字符串看做list,而列表可以通过切片操作来实现翻转:

    a = "I LOVE PYTHON"
    
    reverse_a = a[::-1]

    5、for/else 语句

    在C语言或java语言中,我们寻找一个字符串是否在一个list中,通常会设置一个布尔型变量表示是否找到:

    cities = ['Beijing', 'Shanghai', 'Tianjin', 'Shenzhen','Wuhan']
    tofind = 'Shanghai'
    
    found = False
    for city in cities:
        if tofind == city:
            print('Found')
            found = True
            break
    if not found:
        print('Not found!')

    而python中通过for ... else ... 会使得代码很简洁,注意else中的代码快仅仅是在for循环中没有执行break语句的时候执行:

    cities = ['BeiJing', 'TianJin', 'JiNan', 'ShenZhen', 'WuHan']
    tofind = 'Shanghai'
    
    for city in citiees:
        if tofind == city:
            print('Found')
            break
    else:
        print('Not found!')

    另外,while和try关键字都可以和else搭配使用

    6、迭代对象善用enumerate类

    enumerate类接收两个参数,其中一个是可以地迭代的对象,另外一个是开始的索引。比如,我们想要的打印一份列表的索引机器内容,可以用如下代码实现:

    cities = ['Beijing', 'Shanghai', 'Wuhan']
    
    index = 0 
    for city in cities:
        index = index + 1
        print(index, ':', 'city')

    而通过使用enumerate则极大的简化了代码,这里索引设置为从1开始(默认是从 0 开始):

    cities = ['Beijing', 'Shanghai', 'Wuhan']
    
    for index, ciity in enumerate(cities, 1):
        print(index, ':', city)

    7、通过lambda来定义函数

    lambda可以返回一个可以调用的函数对象,会使得代码更为简洁,若不使用lambda则需要单独定义一个函数:

    def f(x):
        return x*x
    
    map(f, [1,2,3,4,5,6,7,8])

    使用lambda后仅仅使用一行代码:

    map(lambda x: x * x,[1,2,3,4,5,6,7,8] )

    这里注意,lambda生成的是一个可以向其他函数一样使用的函数对象,即

    def f(x);
        return x *x
    
    等价于
    
    lambda x : x*x

    8、应用上下文管理

     在打开文件时,通常是通过捕获异常来进行实现的,并且在finally模块中对文件来进行关闭:

    try:
        file = open('python.txt')
        for line in file:
            print(line)
    except:
        print('File error!')
    finally:
        file.close()

    而通过上下文管理中的with语句可以让代码非常简洁:

    with open('python.txt') as file:
        for line in file:
            print(line)

    9、使用装饰器

    装饰器在Python中的应用非常广泛,其特点是可以再具体函数执行之前或者之后做相关的操作。比如:执行前打印执行函数的相关信息,对函数的参数进行校验,执行后记录函数调用的相关日志等,使用装饰器可以用如下代码实现:

    from time import ctime
    
     def foo():
        print("[%s] %() is called" % (ctime(), foo.__name__))
        print('Hello , Python')

    这样写的问题是业务逻辑中会夹杂参数检查,日志记录等信息,是得代码逻辑不够清晰,所以,这种场合需要使用装饰器:

    from time import ctime 
    
    def deco(func):
        def decorator(*args,**kwargs):
            print("[%s] %s() is called" % (citme(), func,__name__)
            return  func(*args, **kwargs)
        return decorator
    
    
    @deco
    def foo():
        print("Hello Python")

    10、使用生成器

    生成器与列表最大的区别就是,列表是一次行生成的,需要较大的内存空间;而生成器是需要的时候生成的,基本不占用内存空间,生成器分为生成器表达式和生成器函数:

    先看一下列表:

    l = [x for x in range(10)]

    改成生成器只需要将[ .. ]变为(...),即

    g = (x  for x in range(10))

    至于生成器函数,是通过yield关键字来实现的,我们一计算斐斐波那契数列为例,使用列表可以用如下代码来说实现:

    def fib(max):
         n, a, b = 0, 0, 1
        fibonacci = []
        while n < max:
            fibonacci,append(b)
            a, b = b, a + b
            n = n + 1
        return fibonacci

    而使用生成器则变为:

    def fib(max);
        n, a, b = 0, 0, 1
        while n < max:
            yield b
            a, b = b, a+b
            n = n + 1

    11、counter的使用

    通常的词频统计中,我们的思路是:

     需要一个字典,key值存储单词,value存储对应的词频。当遇到一个单词,判断是否在这个字典中,如果是,则词频加1,如果否,则字典中新增这个单词,同时对应的词频设置为1.

    对应的Python代码实现如下:

    # 统计单词出现的次数
    def computeFrequencies(wordList):
        # 词频字典
        wordfrequencies = {}
        
        for word in wordList:
            if word not in wordfrequescies;
            #单词不在单词词频字典中,词频设置为1
                wordfrequescies[word] = 1
            else:
                # 单词在单词词频字典中,词频加   1
                wordfrequencies[word] += 1
        return wordfrequencies

    有没有更简单的方法吗?答案是肯定的,就是使用Counter。collection中的Counter类就完成了这样的功能,他是字典类的一个子类。Python代码变得无比简洁:

    # 统计单词出现的频次
    def computeFrequencies(wordList):
        # 词频字典
        wordfrequencies = Counter(wordList)
        return wordfrequencies

    12、链式比较

    在实际的数字比较中,我们可能需要多次比较多次,比如我们判断学习成绩是否位与某个区间:

    x = 79
    
    >>> x < 80 and x > 70
    True

    变更Pythonic的写法变身链式比较:即:

    x  = 79
    
    >>> 80 < x 90
    False
    
    >>> 70 < x < 80
    True

    这种写法给人的感受也更为直观易懂。

    13、函数返回多个值

    在java语言中,当函数需要返回多个值时,通常的做法是生成一个Response对象,然后将要返回的值写入对象内部,而Python不需要这样做。可以直接返回多个值:

    def f();
        error_code = 0
        error_desc = "成功"
        return error_code, error_desc

    使用的时候也会非常简单:

    code, desc = f()
    print(code, desc)

    14、使用*运算符

    *运算符和 ** 运算符完美的解决了将元组参数、字典参数进行 unpack,从而简化了函数定义的形式,如:

    def fun(*args):
        for eacharg in args:
            print('tuple arg:', eacharg)
    
    fun('I', 'LOVE', 'PYTHON')

    运行的结果:

    tuple arg: I

    tuple arg: love

    tuple arg: Python

    15、找出列表中出现最多的数:

      这是经常遇到的一个问题。解决这个问题的其中一个思路是按照标题 11 提供的词频统计的方法,先统计词频,然后遍历字典,找出具有最大词频的数字,有没有简洁的方式?

    当然,Python代码入下:

    num = [1,2,3,4,4,4,4, 2,3,4,5,6,7,8,9]
    
    ptint(max(set(num), key=num.count))
  • 相关阅读:
    异常
    动态链接库与静态链接库的区别
    OpenBLAS 安装与使用
    Eigen 优化技巧
    C++读取保存为二进制的 numpy 数组
    Sublime Text Windows版使用Conda环境
    Repeater 时间格式化
    C#与js的各种交互
    js 实现精确加减乘除
    常用正则表达式
  • 原文地址:https://www.cnblogs.com/jcjc/p/10844778.html
Copyright © 2011-2022 走看看