教你5招,轻松写出优雅的Python代码

在Python中,一般称优雅的代码为Pythonic。以我的理解,所谓Pythonic就是用Python的方式写出简洁优美的代码。

今天我给大家分享5种简洁优美的代码,相信看完本篇文章后你会对如何编写Python有不一样的理解。

  • 善用内置函数
  • 合理使用数据结构
  • 合理使⽤Python的⾼级并发⼯具
  • 巧妙使⽤装饰器简化代码
  • Python中的设计模式
1、善用内置函数

1.1 enumerate类

enumerate 是⼀个类,但是⽤起来却跟函数⼀样⽅便。不使⽤ enumerate 可能是 Python 新⼿最容易被吐槽的地⽅了。enumerate 其实⾮常简单,接收⼀个可迭代对象,返回 index 和可迭代对象中的元素的组合。

不使⽤enumerate的时候

from __future__ import print_function
L = [ i*i for i in range(5) ]
index = 0
for data in L:
    index += 1
    print(index, ':', data)

正确使⽤enumerate的姿势:

L = [ i*i for i in range(5) ]
for index, data in enumerate(L, 1):
    print(index, ':', data)

不使用enumerate需要4行代码,使用enumerate只需要2行代码。如果想把代码写得简洁优美,大家要时刻记住:在保证代码可读性的前提下,代码越少越好

1.2 any

在内置函数中,像any和all这种函数,是大家都知道,并且觉得很简单,但是使用的时候就想不起来的。我们来看一个具体的例子。

以元组为例,如下所示:

(('t', 0, 'PRIMARY', 1, 'id', 'A', 0, None, None, '', 'BTREE', '', ''),)

我们现在要遍历一个二维的元组,然后判断是否存在Non_unique为0,Null列不为YES的记录。详细了解了具体实现以后,我们写下了下面的代码:

 def has_primary_key():
     for row in rows:
         if row[1] == 0 and row[9] != 'YES':
             return True
    return False

如果我们使用any函数的话,代码将会更短。

def has_primary_key():
    return any(row[1] == 0 and row[9] != 'YES' for row in rows):
2、善用内置函数

我们再来看一个类似的例子,获取元素且删除:

L = [1, 2, 3, 4]
last = L[-1]
L.pop()
print(last)  # 删除元素
print(L)  # 最终元素
-----result--------
4
[1, 2, 3]

这里我们又多此一举了。在调用L.pop()函数的时候,本身就会返回给我们需要pop的数,其实我们可以这样:

L = [1, 2, 3, 4]
last = L.pop()
print(last)  # 删除元素
print(L)  # 最终元素
-----result--------
4
[1, 2, 3]
3、合理使⽤Python的⾼级并发⼯具

很多时候,我们要用并发编程,并不用自己手动启动一个线程或进程,完全可以使用Python提供的并发工具。内置的map是单线程运行的,如果涉及到网络请求或者大量的cpu计算,则速度相对会慢很多,出现了并发的map,如下所示:

import requests
from multiprocessing import Pool
def get_website_data(url):
    r = requests.get(url)
    return r.url
def main():
    urls = ['http://www.google.com',
    'http://www.baidu.com',
    'http://www.163.com']
    pool = Pool(2)
    print(pool.map(get_website_data, urls))
main()

为了与线程兼容,该模块还提供了multiprocessing.dummy,用以提供线程池的实现,如下所示:

from multiprocessing.dummy import Pool

使用Pool,我们可以快速的在线程池和进程池之间来回切换,最重要的是,使用高级的并发工具不那么容易出错。

4、巧妙使⽤装饰器简化代码

装饰器可能是Python面试中被问的最多的知识了。之所以如此频繁的出现,是因为,装饰器确实是个好东西。

举个例⼦,我们有两个模块,A模块要发消息给B模块,B模块检查A模块发送过来的参数,没有问题就进⾏处理,对于检查参数这个操作,如果我们使⽤装饰器的话,代码将会是下⾯这样:

import inspect
import functools
def check_args(parameters):
    """check parameters of action"""
    def decorated(f):
        """decorator"""
        @functools.wraps
        def wrapper(*args, **kwargs):
        """wrapper"""
            func_args = inspect.getcallargs(f, *a
            msg = func_args.get('msg')
            for item in parameters:
                if msg.body_dict.get(item) is Non
                return False, "check failed,
            return f(*args, **kwargs)
        return wrapper
    return decorated
    
使⽤的时候:

class AsyncMsgHandler(MsgHandler):
  @check.check_args(['ContainerIdentifier', 'MonitorSecretKey','InstanceID','UUID'])
  def init_container(self, msg):
    pass
5、Python中的设计模式

对Python的模块熟悉的⼈会知道,在Python中,模块只初始化⼀次,所有变量归属于某个模块,import机制是线程安全的。所以,模块本身是天然的单例实现。因此,我们可以借助模块来实现单例模式。

下⾯这个例⼦创建了⼀个函数,令其返回含有货币汇率的字典,这个函数可以被多次调⽤,但是,⼤部分情况下,汇率数据只获取⼀次就够了,⽆须每次调⽤时都获取⼀遍。

def get():
    if not get.rates:
        _URL = 'http://www.bankofcanada.ca/stats/
        with urllib.request.urlopen(_URL) as file
            for line in file:
            # get.rates[key] = float(data)
            pass
    return get.rates
get.rates = {}

在这段代码中,尽管没有引⼊类,但我们依然把汇率数据做成了"单例数据值"。⼤家可以看到,在Python中,单例可以直接使⽤模块来实现,⾮常的简单。

推荐阅读

更多精彩内容,关注微信公众号『Python学习与数据挖掘』

为方便技术交流,本号开通了技术交流群,有问题请添加小助手微信号:connect_we,备注:加群来自CSDN,欢迎转载,收藏,码字不易,喜欢文章就点赞一下!谢啦
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_38037405/article/details/108429099