title: 可爱的豆子——使用Beans思想让Python代码更易维护

toc: false

comments: true

date: 2016-06-19 21:43:33

tags: [Python, Java, 经验]

category: Python

我曾经是一个对Java非常反感的人,因为Java的语法非常啰嗦。而用惯了动态类型的Python再使用静态类型的Java就会觉得多出了很多的工作量。

因为工作的关系,我开始使用Java来做项目。在这个过程中,我发现Java在某些方面确实和Python不一样。

有一句话说的好:

语言决定了世界观。

当我Java用的越来越多的时候,我渐渐发现我不是那么讨厌它了。

今天我要讲的,是我从Java里面学到的,一个被称为JavaBeans的东西。

In computing based on the Java Platform, JavaBeans are classes that encapsulate many objects into a single object (the bean). They are serializable, have a zero-argument constructor, and allow access to properties using getter and setter methods.

一句话概括起来: 当一些信息需要使用类似于字典套字典套列表这种很深的结构来储存的时候,请改用类来储存。

在Python里面,我以前会写这样的代码:

person_list = [{
'name': 'kingname',
'age': 23,
'sex': 'male'
'detail': {
'address': 'xxx',
'work': 'engineer',
'salary': 100000
}
},
{
'name': 'xiaoming',
'age': 65,
'sex': 'male'
'detail': {
'address': 'yyy',
'work': 'pm',
'salary': 0.5
}
}]

由于Python动态类型的特点,字典里面的value经常是包含了各种类型,有时候,字典里面包含了字典,里面的字典里面还有列表,这个内部字典里面的列表里面又包含了字典……

当我刚刚开始写Java代码的时候,也会保留了这个坏习惯,于是我定义的一个变量类似于这样:

public Map<String, List<Map<String, Map<String, Object>>>> info = .....

并且由于Java是静态类型语言,有时候Map里面的Value类型还不一致,需要使用Object来代替,等要使用的时候再做类型转换。

对于这样的写法,真可谓是写代码一时爽,调试代码火葬场。我过几天读自己的代码,自己都不知道这个字典里面有哪些内容,也不知道它们有哪些类型,必须到定义的地方去看。

我的Mentor看了我的Java代码以后,让我去用一下JavaBeans,于是我的世界瞬间就简洁多了。后来我将JavaBeans的思想用到Python中,果然Python代码也变得好看多了。

使用上面person_list这个复杂的结构为例,我用JavaBeans的思想,在Python里面重构它:

class Person(object):
def __init__(self, name='', age=0, sex='', detail=None):
self._name = name
self._age = age
self._sex = sex
self._detail = detail @property
def name(self):
return self._name @name.setter
def name(self, new_name):
self._name = new_name @property
def age(self):
return self._age @age.setter
def age(self, new_age):
self._age = new_age @property
def sex(self):
return self._sex @sex.setter
def sex(self, new_sex):
self._sex = new_sex @property
def detail(self):
return self._detail @detail.setter
def detail(self, new_detail):
self._detail = new_detail
class Detail(object):
def __init__(self, address='', work='', salary=0):
self._address = address
self._work = work
self._salary = salary @property
def address(self):
return self._address @address.setter
def address(self, new_address):
self._address = new_address @property
def work(self):
return self._work @work.setter
def work(self, new_work):
self._work = new_work @property
def salary(self):
return self._salary @salary.setter
def salary(self, new_salary):
self._salary = new_salary

从这里可以看到,我把字典变成了类。于是,当我想保存我自己的信息和小明的时候,我就可以这样写:

detail_kingname = Detail(address='xxx', work='engineer', salary=10000),
kingname = Person(name='kingname', age=23, sex='male', detail=detail_kingname) detail_xiaoming = Detail(address='yyy', work='pm', salary=0.5),
xiaoming = Person(name='xiaoming', age=65, sex='male', detail=detail_xiaoming) person_list = [kingname, xiaoming]

这样写,虽然说代码量确实翻了不止一倍,但是当我们后期维护的时候或者遇到问题来调试代码,我们就能发现这样写的好处。

举一个很简单的例子,在写了代码一年以后,我已经对这段代码没有多少印象了,现在我得到了变量person_list, 我想查看每个人的工资。首先,由于PersonDetail这两个类是已经定义好的,分别放在Person.pyDetail.py两个文件中,于是我点开它们,就知道,原来工资是保存在Detail这个类中的,关键词是salary, 而Detail又是保存在Person中的,关键词是detail

所以要查看每个人的工资,我可以这样写:

for person in person_list:
detail = person.detail
salary = detail.salary
print(salary)

但是如果我使用的是最上面字典的那种方式,那么情况就没有这么简单了。因为我不知道工资是在这个字典的什么地方。于是我首先要找到person_list是在哪里初始化的,然后看它里面有什么。在这个例子中,我是一次性把整个列表字典初始化完成的,直接找到列表初始化的地方就知道,原来这个person_list下面有很多个字典,字典有一个key 叫detail,这个detail的value本身又是一个字典,它下面的keysalary保存了工资的信息。这似乎还比较方便。但是如果字典里面的信息不是一次性初始化完成的呢?万一detail这一个key是后面再加的呢?于是又要去找detail初始化的地方……

第二个好处,使用Beans的时候,每个关键字是定义好的,salary就只能叫做salary,如果写成了salarv, 集成开发环境会立刻告诉你,Detail没有salarv这个属性。但是如果使用字典的方式,我在给字典赋值的时候,一不小心:

detail['salarv'] = 0.5

由于这里的salarv是字符串,所以集成开发环境是不会报错的,只有等你运行的时候,尝试读取detail['salary']里面的值,Python会告诉你:

Traceback (most recent call last):
File "xxx.py", line 1, in <module>
KeyError: 'salary'

总结

将JavaBeans的思想用在Python中,避免字典套字典这种深层嵌套的情况,对于一些需要反复使用的字典,使用类来表示。这样做,别人读代码的时候会更加的容易,自己开发的时候,也会避免出现问题。

本文首发地址: http://kingname.info/2016/06/19/bean-in-python/ 转载请注明出处。

可爱的豆子——使用Beans思想让Python代码更易维护的更多相关文章

  1. 让 Python 代码更易维护的七种武器——代码风格(pylint、Flake8、Isort、Autopep8、Yapf、Black)测试覆盖率(Coverage)CI(JK)

    让 Python 代码更易维护的七种武器 2018/09/29 · 基础知识 · 武器 原文出处: Jeff Triplett   译文出处:linux中国-Hank Chow    检查你的代码的质 ...

  2. 程序员需要掌握的七种 Python 代码更易维护的武器

    检查你的代码风格 PEP 8 是 Python 代码风格规范,它规定了类似行长度.缩进.多行表达式.变量命名约定等内容.尽管你的团队自身可能也会有稍微不同于 PEP 8 的代码风格规范,但任何代码风格 ...

  3. pythonic-让python代码更高效

    何为pythonic? pythonic如果翻译成中文的话就是很python.很+名词结构的用法在中国不少,比如:很娘,很国足,很CCTV等等. 我的理解为,很+名词表达了一种特殊和强调的意味.所以很 ...

  4. 让Python代码更快运行的 5 种方法

    不论什么语言,我们都需要注意性能优化问题,提高执行效率.选择了脚本语言就要忍受其速度,这句话在某种程度上说明了Python作为脚本语言的不足之处,那就是执行效率和性能不够亮.尽管Python从未如C和 ...

  5. Pycharm配置autopep8让Python代码更符合pep8规范

    一.何为pep8? PEP 8官方文档 -- Style Guide for Python Code PEP8中文翻译(转) 二.Pycharm中配置pep8 Pycharm本身是有pep8风格检测的 ...

  6. 学习 27 门编程语言的长处,提升你的 Python 代码水平

    Python猫注:Python 语言诞生 30 年了,如今的发展势头可谓如火如荼,这很大程度上得益于其易学易用的优秀设计,而不可否认的是,Python 从其它语言中偷师了不少.本文作者是一名资深的核心 ...

  7. 一些你需要知道的Python代码技巧

    被人工智能捧红的 Python 已是一种发展完善且非常多样化的语言,其中肯定有一些你尚未发现的功能.本文或许能够让你学到一些新技巧.   Python 是世界上最流行.热门的编程语言之一,原因很多,比 ...

  8. 教你一招,提升你Python代码的可读性,小技巧

    Python的初学者,开发者都应该知道的代码可读性提高技巧,本篇主要介绍了如下内容: PEP 8是什么以及它存在的原因 为什么你应该编写符合PEP 8标准的代码 如何编写符合PEP 8的代码 为什么我 ...

  9. python代码风格-PEP8

    转载自http://www.douban.com/note/134971609/ Python 的代码风格由 PEP 8 描述.这个文档描述了 Python 编程风格的方方面面.在遵守这个文档的条件下 ...

随机推荐

  1. solr服务中集成IKAnalyzer中文分词器、集成dataimportHandler插件

    昨天已经在Tomcat容器中成功的部署了solr全文检索引擎系统的服务:今天来分享一下solr服务在海量数据的网站中是如何实现数据的检索. 在solr服务中集成IKAnalyzer中文分词器的步骤: ...

  2. 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车

     阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ...

  3. python+uwsgi导致redis无法长链接引起性能下降问题记录

    今天在部署python代码到预生产环境时,web站老是出现redis链接未初始化,无法连接到服务的提示,比对了一下开发环境与测试环境代码,完全一致,然后就是查看各种日志,排查了半天也没有查明是什么原因 ...

  4. pt-ioprofile

    pt-ioprofile是用来观察特定进程的IO信息的. 该脚本是用shell写的,有两方面的作用: pt-ioprofile does two things: ) ) is not performe ...

  5. C# 数组的交集、差集、并集

    C# 数组的交集.差集.并集 工作中经常会用这方面的知识来检查那些字段是必须输入的,那些是禁止输入. using System; using System.Collections.Generic; u ...

  6. Java compiler level does not match解决方法

    从别的地方导入一个项目的时候,经常会遇到eclipse/Myeclipse报Description  Resource Path Location Type Java compiler level d ...

  7. Dynamics CRM 之ADFS 使用 WID 的独立联合服务器

    ADFS 的使用 WID 的独立联合服务器适用于自己的测试环境,常用的就是在虚机中使用. 拓扑图如下: wID:联合身份验证服务配置为使用 Windows 内部数据库

  8. 跟着老男孩教育学Python开发【第三篇】:Python函数

    set 无序,不重复,可嵌套. 函数 创建函数: 1.def关键字,创建函数 2.函数名 3.() 4.函数体 5.返回值 发邮件函数 def sendmail():     import smtpl ...

  9. Prometheus 系统监控方案 一

    最近一直在折腾时序类型的数据库,经过一段时间项目应用,觉得十分不错.而Prometheus又是刚刚推出不久的开源方案,中文资料较少,所以打算写一系列应用的实践过程分享一下. Prometheus 是什 ...

  10. git图像化界面GUI的使用

    GIT学习笔记 一.        基础内容 1.git是一个版本控制软件,与svn类似,特点是分布式管理,不需要中间总的服务器,可以增加很多分支. 2.windows下的git叫msysgit,下载 ...