前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python工匠:如何更好地使用变量

Python工匠:如何更好地使用变量

作者头像
腾讯NEXT学位
修改2019-05-16 17:02:39
9520
修改2019-05-16 17:02:39
举报

编程某种意义上是一门『手艺』,因为优雅而高效的代码,就如同完美的手工艺品一样让人赏心悦目。

致“匠人”

前面讲了如何为变量取一个好名字,下面我们谈谈在日常使用变量时,应该注意的一些小细节。

1

保持一致性

如果你在一个方法内里面把图片变量叫做 photo,在其他的地方就不要把它改成 image,这样只会让代码的阅读者困惑:『image 和 photo 到底是不是同一个东西?』

另外,虽然 Python 是动态类型语言,但那也不意味着你可以用同一个变量名一会表示 str 类型,过会又换成 list。同一个变量名指代的变量类型,也需要保持一致性。

2

少用 globals()/locals()法

也许你第一次发现 globals()/locals() 这对内建函数时很兴奋,迫不及待的写下下面这种极端『简洁』的代码:

def render(request, user_id, trip_id):    user = User.objects.get(id=user_id)    trip = get_object_or_404(Trip, pk=trip_id)    is_suggested = is_suggested(user, trip)    # 利用 locals() 节约了三行代码,我是个天才!    return render(request, 'trip.html', locals())

千万不要这么做,这样只会让读到这段代码的人(包括三个月后的你自己)痛恨你,因为他需要记住这个函数内定义的所有变量(想想这个函数增长到两百行会怎么样?),更别提 locals() 还会把一些不必要的变量传递出去。

更何况, The Zen of Python(Python 之禅) 说的清清楚楚:Explicit is better than implicit.(显式优于隐式)。所以,还是老老实实把代码写成这样吧:

return render(request, 'trip.html', {        'user': user,        'trip': trip,        'is_suggested': is_suggested    })

3

变量定义尽量靠近使用

这个原则属于老生常谈了。很多人(包括我)在刚开始学习编程时,会有一个习惯。就是把所有的变量定义写在一起,放在函数或方法的最前面。

def generate_trip_png(trip):    path = []    markers = []    photo_markers = []    text_markers = []    marker_count = 0    point_count = 0    ... ...

这样做只会让你的代码『看上去很整洁』,但是对提高代码可读性没有任何帮助。

更好的做法是,让变量定义尽量靠近使用。那样当你阅读代码时,可以更好的理解代码的逻辑,而不是费劲的去想这个变量到底是什么、哪里定义的?

4

合理使用 namedtuple/dict 

合理使用 namedtuple/dict 来让函数返回多个值。

Python 的函数可以返回多个值,下面是几个不错的示例:

def latlon_to_address(lat, lon):    return country, province, city
# 利用多返回值一次解包定义多个变量country, province, city = latlon_to_address(lat, lon)

但是,这样的用法会产生一个小问题:如果某一天, latlon_to_address 函数需要返回『城区(District)』时怎么办?

如果是上面这种写法,你需要找到所有调用 latlon_to_address 的地方,补上多出来的这个变量,否则 ValueError: too many values to unpack 就会找上你:

country, province, city, district = latlon_to_address(lat, lon)# 或者使用 _ 忽略多出来的返回值country, province, city, _ = latlon_to_address(lat, lon)

对于这种可能变动的多返回值函数,使用 namedtuple/dict 会更方便一些。当你新增返回值时,不会对之前的函数调用产生任何破坏性的影响:

# 1. 使用 dictdef latlon_to_address(lat, lon):    return {        'country': country,        'province': province,        'city': city    }
addr_dict = latlon_to_address(lat, lon)
# 2. 使用 namedtuplefrom collections import namedtuple
Address = namedtuple("Address", ['country', 'province', 'city'])
def latlon_to_address(lat, lon):    return Address(        country=country,        province=province,        city=city    )
addr = latlon_to_address(lat, lon)

不过这样做也有坏处,因为代码对变更的兼容性虽然变好了,但是你不能继续用之前 x, y = f() 的方式一次解包定义多个变量了。取舍在于你自己。

5

控制单个函数内的变量数量

人脑的能力是有限的,研究表明,人类的短期记忆只能同时记住不超过十个名字。所以,当你的某个函数过长(一般来说,超过一屏的的函数就会被认为有点过长了),包含了太多变量时。请及时把它拆分为多个小函数吧。

6

及时删掉那些没用的变量

这条原则非常简单,也很容易做到。但是如果没有遵守,那它对你的代码质量的打击是毁灭级的。会让阅读你代码的人有一种被愚弄的感觉。

def fancy_func():    # 读者心理:嗯,这里定义了一个 fancy_vars    fancy_vars = get_fancy()    ... ...(一大堆代码过后)
    # 读者心理:这里就结束了?之前的 fancy_vars 去哪了?被猫吃了吗?    return resul

所以,请打开 IDE 的智能提示,及时清理掉那些定义了但是没有使用的变量吧。

7

能不定义变量就不定义

有时候,我们定义变量时的心理活动是这样的:『嗯,这个值未来说不定会修改/二次使用』,让我们先把它定义成变量吧!

def get_best_trip_by_user_id(user_id):    user = get_user(user_id)    trip = get_best_trip(user_id)    result = {        'user': user,        'trip': trip    }    return result

其实,你所想的『未来』永远不会来,这段代码里的三个临时变量完全可以去掉,变成这样:

def get_best_trip_by_user_id(user_id):    return {        'user': get_user(user_id),        'trip': get_best_trip(user_id)    }

没有必要为了那些可能出现的变动,牺牲代码当前的可读性。如果以后有定义变量的需求,那就以后再加吧。

结束语

变量作为程序语言的重要组成部分,值得我们在定义和使用它时,多花一丁点时间思考一下,那样会让你的代码变得更优秀。

原文作者:腾讯高级工程师 朱雷

来源:腾讯内部KM论坛

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯NEXT学院 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档