一、数组声明 两种形式(方括号位置放变量前后都可以): int arr[ ]; int[ ] arr2; 二、数组初始化 数组初始化也有两种形式,如下(使用new或不使用new): int arr[] = new int[]{1, 3, 5, 7, 9}; int[] arr2 = {2, 4, 6, 8, 10}; 三、遍历数组 遍历数组可用for/foreach,如下: for循环略 int arr[] = new int[]{1, 3, 5, 7 ,9}; for (int x: arr) { System.out.print(x + "\t"); } 四、Arraysfill填充数组(修改数组) 使用Arrays类的静态方法,需要import包java.util.Arrays,定义了许多重载方法。 void fill(int[] a, int val)全部填充 void fill(int[] a, int fromIndex, int toIndex, int val)填充指定索引的元素 左闭右开
1 2 3 |
int[] arr = new int[]{6,6,6,6,6,6}; Arrays.fill(arr, 8); //8,8,8,8,8,8 Arrays.fill(arr3, 1, 3, 9); //6,9,9,8,8,8 |
五、Arrayssort对数组排序(使用Arrays.调用) void sort(int[] a)全部排序 默认升序 void sort(int[] a, int fromIndex, int toIndex)排序指定索引的元素
1 2 3 |
int [] array=new int[]{3,7,8,2,1,9}; Arrays.sort(array); //全排序 Arrays.sort(array,2,5); //2到5排序 |
六、ArrayscopyOf复制数组 int[] copyOf(int[] original, int newLength)复制数组,指定新数组长度 int[] copyOfRange(int[] original, int from, int to)复制数组,指定所复制的原数组的索引
1 2 3 |
int [] array=new int[]{3,7,8,2,1,9}; array2=Arrays.copyOf(array,3); //新数组的长度为3 array3=Arrays.copyOfRange(array,3,5); //复制第三到五个元素 |
七、检查数组中是否包含某一个值 先使用Arrays.asList()将Array转换成List<String>,这样就可以用动态链表的contains函数来判断元素是否包含在链表中 […]
View Details简述 方法其实有很多种的。我先放一些,之后有再遇到对应代码再放上来。 最简单的当然是一个个找进行对比的方法啦~ 当然还是有一些有趣的操作的 实例一:
1 2 3 4 5 6 |
import java.util.Arrays; public static int MAX(int[] arr) { Arrays.sort(arr); return arr[arr.length-1]; } |
就是先排序再来得到结果 实例二 这个是菜鸟教程上的一份代码
1 2 3 4 5 6 7 8 9 10 11 12 |
import java.util.Arrays; import java.util.Collections; public class Main { public static void main(String[] args) { Integer[] numbers = { 8, 2, 7, 1, 4, 9, 5}; int min = (int) Collections.min(Arrays.asList(numbers)); int max = (int) Collections.max(Arrays.asList(numbers)); System.out.println("最小值: " + min); System.out.println("最大值: " + max); } } |
实例三:
1 2 3 4 |
import java.util.Arrays public static int MAX(int[] arr) { return Arrays.stream(arr).max().getAsInt(); } |
from:https://blog.csdn.net/a19990412/article/details/81296234
View DetailsString[]与List的相互转换 1.0 String[]与List的相互转换
1 2 |
String[] arr = new String[]{"s1","s2","s3"}; List<String> list = Arrays.asList(arr); |
1.2 List转String[]
1 2 3 4 5 |
List<String> list = new ArrayList<String>(); list.add("s1"); list.add("s2"); list.add("s3"); String[] arr = list.toArray(new String[list.size()]); |
字符数组char[]和字符串String之间的转换 2.0 使用String.valueOf()将字符数组转换成字符串
1 2 3 4 5 6 7 |
void (){ char[] s={'A','G','C','T'}; String st=String.valueOf(s); System.out.println("This is : "+st); } >> This is : AGCT |
2.1使用.toCharArray()将字符串转换成字符数组
1 2 3 4 5 6 7 8 9 10 |
String str="AGCT"; char[] s=str.toCharArray(); for (int i=0;i<str.length();i++){ System.out.println("This s[i] "+i+s[i]); } This s[i] 0 A This s[i] 1 G This s[i] 2 C This s[i] 3 T |
from:https://blog.csdn.net/qq_41076577/article/details/106909006
View Details前言(废话) 昨天抽了点时间在网上搜列了一个开源项目,项目挺完整的,前后台分离还带有微信小程序,我Clone下代码,经过一番倒腾,嘿~还真就跑起来了。在这个过程中,体验了一把VUE项目工程细节,因为之前没有接触过这一块,所以还是花费了点时间,好在开源项目的QQ群里楼主帮忙看了一下,才得以顺利往后进行。后来也有很多网友向楼主提问,也抛出了一些问题,其中有个问题到引起了我的注意。 有个小伙伴执行SQL的时候报错了,以为项目中给的SQL脚本不全,但是在群里他并没有给出报错细节的截图,楼主后来也就提示了他一句MySQL版本需要在5.7以上,但是后面就没有更多消息了。 今天早上我还在上班路上,群里的小伙伴就私信我,说能否帮他看下数据库的问题。等我到了公司再回复他的时候,他告诉我说数据库问题已经解决了,我追问了一下细节,原来是开源项目中的数据库建表语句中包含JSON类型字段,导致了他批量执行SQL脚本不成功。其实这样的问题,在执行脚本的时候遇到错误是有日志的,详细看下日志应该明了。 我其实是没有注意到这个细节的,因为我前天安装的数据库就直接上了8.0,屏蔽了这个问题,但是,MySQL数据库现在支持JSON类型,挺新奇的,因为之前没有用过,并不熟悉,所以这一次,让我逮到个了解它的机会。 关于MySQL的JSON类型 JSON估计大家伙都熟悉了,我就不再介绍这方面内容。其实在MySQL数据库中,也直到5.7这个版本,才开始引入JSON数据类型,在此之前如果想在表中保存JSON格式类型的数据,则需要依靠varchar或者text之类的数据类型,如果在低于5.7版本的数据库中使用了JSON类型来建表,显然是不会成功的。 (截图为MySQL官网文档) 如何使用JSON类型 建表 在MySQL中创建具有JSON数据列的表,其实和数据类型没有太大区别,具体举例如下:
1 2 3 4 |
CREATE TABLE tab_base_info ( id BIGINT NOT NULL PRIMARY KEY auto_increment, content json ); |
新增数据 插入一条语句,注意看JSON数据列的内容:
1 2 3 4 5 |
INSERT INTO tab_base_info (content) VALUES ( '{"author": "Captain&D", "blog": "https://www.cnblogs.com/captainad"}' ); |
这里需要提醒的是: JSON列存储的数据要么是NULL,要么必须是JSON格式数据,否则会报错。 JSON数据类型是没有默认值的(声明时"DEFAULT NULL")。 JSON数据类型意义 其实,没有JSON数据类型的支持,我们一样可以通过varchar类型或者text等类型来保存这一格式的数据,但是,为什么还要专门增加这一数据格式的支持呢?其中肯定有较varchar或者text来存储此类型更优越的地方。 保证了JSON数据类型的强校验,JSON数据列会自动校验存入此列的内容是否符合JSON格式,非正常格式则报错,而varchar类型和text等类型本身是不存在这种机制的。 MySQL同时提供了一组操作JSON类型数据的内置函数。 更优化的存储格式,存储在JSON列中的JSON数据会被转成内部特定的存储格式,允许快速读取。 可以基于JSON格式的特征支持修改特定的键值。(即不需要把整条内容拿出来放到程序中遍历然后寻找替换再塞回去,MySQL内置的函数允许你通过一条SQL语句就能搞定) MySQL关于JSON的内置函数 MySQL关于JSON数据格式的操作提供了很多高效率的内置函数,我们可以从MySQL官网上找到很详细的介绍和使用说明,下面贴一张JSON函数的指南: (截图为MySQL官方文档) 其实我们从JSON功能介绍的主页也可以看到,这些内置函数支持我们创建、查找、替换和返回值等相关的操作,像我们替换指定内容的操作就可以使用JSON_REPLACE()这个函数,不过最后实现通过纯SQL语句执行最终的内容替换,你还需要通过执行UPDATE语句,比如:
1 2 3 |
UPDATE tab_base_info SET content = json_replace(content, '$.author', "tom") WHERE id = 1; |
其中“$.***”表示找到JSON内容中匹配的修改字段。 更多关于这些内置函数的用法,大家都可以到官网(链接请查看本文参考资料)的文档上去查阅,写的十分详细而且还有举例。 参考资料: 1、https://zhuanlan.zhihu.com/p/31823258 2、https://dev.mysql.com/doc/refman/5.7/en/json-functions.html from:https://www.cnblogs.com/captainad/p/11176127.html
View DetailsDB-Engines 4 月份流行度排行已更新(基于 3 月份的整体数据变化)。 从总榜来看,前十数据库的排名和上个月保持一致。虽然排名没有变动,但单个数据库的分数却变化不少。稳居前三的 Oracle、MySQL 和 Microsoft SQL Server 分数出现了较大幅度的下跌,分别减少 46.82、34.14 和 7.33 分。其中 SQL Server 分数已经连续下跌了两个月。若与去年同期的数据相比,三者下跌的分数平均已达到 64 分。 后起之秀 PostgreSQL 和 MongoDB 依旧保持着稳步上升的趋势,分数与上个月相比有小幅度增加,与去年同期相比也平均增加了 40 分左右。 ▲ 前十数据库的分数变化走向 对于排名 20 之后的数据库,以年为维度,排名显著上升的数据库有 Snowflake 和 Clickhouse,Snowflake 由去年同时期的第 100 名上升到现在的第 29 名,后者也从第 71 名上升至第 50 名。两者都属于云数据仓库,Snowflake 的母公司去年上市后更是获得巴菲特青睐,股价飙升。相信这也是它排名上升的主要原因。 最后看看各类型数据库的排名情况。 关系数据库前 10 名 Key-Value 数据库前 10 名 文档数据库前 10 名 时序数据库前 10 名 图数据库前 10 名 DB-Engines 根据流行度对数据库管理系统进行排名,排名每月更新一次。排名的数据依据 5 个不同的指标: Google 以及 Bing 搜索引擎的关键字搜索数量 Google Trends 的搜索数量 Indeed 网站中的职位搜索量 LinkedIn 中提到关键字的个人资料数 Stackoverflow 上相关的问题和关注者数量 这份榜单分析旨在为数据库相关从业人员提供一个技术方向的参考,其中涉及到的排名情况并非基于产品的技术先进程度或市场占有率等因素。无论排名先后,选择适合与企业业务需求相比配的技术才是最重要的。 from:https://www.oschina.net/news/135658/db-engines-ranking-202104
View Details背景 Element UI 是 PC 端比较流行的 Vue.js UI 框架,它的组件库基本能满足大部分常见的业务需求。但有时候会有一些定制性比较高的需求,组件本身可能没办法满足。最近在项目里就碰到了。 很多页面都需要用到表格组件el-table。如果没有给el-table-column指定宽度,默认情况下会平均分配给剩余的列。在列数比较多的情况,如果el-table宽度限定在容器内,单元格里的内容就会换行。强制不换行,内容要么在单元格内滚动,要么就会溢出或被截断。 产品想要的效果是:内容保持单行显示,列间距保持一致,表格超出容器允许水平滚动。el-table-column是支持设置固定宽度的,在内容宽度可预知的情况下,也能满足这个需求。问题就在于如何让列宽动态适应内容的宽度。在官方文档也没找到这样的选项,应该是组件本身不支持。 技术方案 于是想到了动态计算内容宽度的方案。网上也有人提过这个思路,做法是根据内容字符数来计算宽度。这种方法有几个局限: 内容必须是文本 不同字符宽度不一,结算结果不够准确 需要在渲染前操作数据,不利于解耦 我采用了另一种思路,还是动态计算内容宽度,但是根据实际渲染后的 DOM 元素宽度,这样就能解决上面三个问题。 具体怎么做呢?通过查看渲染后的 DOM 元素发现,el-table 的表头和内容分别用了一个原生table,通过colgroup设置每列的宽度。就从这里入手,col的name属性值和对应的 td的class值是一致的,这样就可以遍历对应列的所有单元格,找出宽度最大的单元格,用它的内容宽度加上一个边距作为该列的宽度。 具体实现 怎么计算内容宽度呢?这是个比较关键的步骤。渲染后的每个单元格有个.cell类,用white-space: nowrap; overflow: auto;设置为不允许换行,内容超出后可滚动,同时设置display: inline-block;以便计算实际内容宽度。这样,最终的宽度可通过.cell元素的scrollWidth属性得到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function adjustColumnWidth(table) { const colgroup = table.querySelector("colgroup"); const colDefs = [...colgroup.querySelectorAll("col")]; colDefs.forEach((col) => { const clsName = col.getAttribute("name"); const cells = [ ...table.querySelectorAll(`td.${clsName}`), ...table.querySelectorAll(`th.${clsName}`), ]; // 忽略加了"leave-alone"类的列 if (cells[0]?.classList?.contains?.("leave-alone")) { return; } const widthList = cells.map((el) => { return el.querySelector(".cell")?.scrollWidth || 0; }); const max = Math.max(...widthList); const padding = 32; table.querySelectorAll(`col[name=${clsName}]`).forEach((el) => { el.setAttribute("width", max + padding); }); }); } |
中间的探索过程比较繁琐,但最终的代码实现却非常简洁。在什么时候触发列宽计算呢?自然是组件渲染完成后。为了方便重用,我采用了 Vue 自定义指令的方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Vue.directive("fit-columns", { update() {}, bind() {}, inserted(el) { setTimeout(() => { adjustColumnWidth(el); }, 300); }, componentUpdated(el) { el.classList.add("r-table"); setTimeout(() => { adjustColumnWidth(el); }, 300); }, unbind() {}, }); |
更进一步,我封装了一个 Vue 插件叫v-fit-columns,已经发布到 npm 仓库,直接安装即可使用。 安装:
1 |
npm install v-fit-columns --save |
引入:
1 2 3 |
import Vue from 'vue'; import Plugin from 'v-fit-columns'; Vue.use(Plugin); |
使用:
1 2 3 4 5 |
<el-table v-fit-columns> <el-table-column label="No." type="index" class-name="leave-alone"></el-table-column> <el-table-column label="Name" prop="name"></el-table-column> <el-table-column label="Age" prop="age"></el-table-column> </el-table> |
源码仓库在这:https://github.com/kaysonli/v-fit-columns ,欢迎各位不吝赐教和 Star! 总结 这个方案多少有点 Hack 的意味,只顾实现需求,可能在其他方面还有点瑕疵,比如渲染完后会稍微闪一下(因为要重新调整宽度,会出现 reflow)。不过从最终实现的效果来看,还算令人满意,至少产品经理提着他的两米大刀走了……他可是为了这个效果,蹲守在我电脑前半个下午,非要我实现不可!在手摸手的胁迫下,总算完事交差了…… from:https://www.cnblogs.com/lzkwin/p/13575805.html
View Details将日期时间转换为指定格式,如:YYYY-mm-dd HH:MM表示2019-06-06 19:45
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function dateFormat(fmt, date) { let ret; const opt = { "Y+": date.getFullYear().toString(), // 年 "m+": (date.getMonth() + 1).toString(), // 月 "d+": date.getDate().toString(), // 日 "H+": date.getHours().toString(), // 时 "M+": date.getMinutes().toString(), // 分 "S+": date.getSeconds().toString() // 秒 // 有其他格式化字符需求可以继续添加,必须转化成字符串 }; for (let k in opt) { ret = new RegExp("(" + k + ")").exec(fmt); if (ret) { fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0"))) }; }; return fmt; } |
用法:
1 2 3 |
let date = new Date() dateFormat("YYYY-mm-dd HH:MM", date) >>> 2019-06-06 19:45` |
2020-11-23: 如果对日期时间处理的需求较多, 推荐moment.js这个日期处理类库, 简单方便. 作者:雷子_ 链接:https://www.jianshu.com/p/49fb78bca621 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
View Details在watch中使用this要注意,不能用箭头函数,否则会出错,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<template> </template> <script> export default{ data(){ return { isLogin: false } }, watch:{ isLogin: (newVal, oldVal) => { newVal && this.updateLogin() } }, methods:{ updateLogin(){ console.log(`update login`) } } } </script> <style scoped> </style> |
箭头函数要改为function的形式,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<template> </template> <script> export default{ data(){ return { isLogin: false } }, watch:{ isLogin: function(newVal, oldVal) { newVal && this.updateLogin() } }, methods:{ updateLogin(){ console.log(`update login`) } } } </script> <style scoped> </style> |
from:https://blog.csdn.net/liubangbo/article/details/115242420
View Details| 前言 相信绝大部分开发人员、DBA都听过范式这个词,在MySQL中有第一范式、第二范式、第三范式、BCNF范式等,在开发中也有相应的范式,专业词汇叫编程范式(ProgrammingParadigm)。由于笔者能力、精力都有限,本篇主要通过针对同一业务场景,基于编程范式的概念,核心原理以及用例实现来对比不同范式及其实现业务功能的差异。 范式分类 如图1所示,范式可以简单分为三类: 图1: 范式的简单分类 范式和语言的关系 图2: 范式和语言的关系 与成百种编程语言相比,编程范式要少得多,如图2所示,共有27种范式。多数范式之间仅相差一个或几个概念,比如图中的函数编程范式,在加入了状态(state)之后就变成了面向对象编程范式。 | 编程范式 图3: 华山派剑气之争 过程式编程的核心在于模块化,在实现过程中使用了状态,依赖了外部变量,导致很容易影响附近的代码,可读性较少,后期的维护成本也较高。 函数式编程的核心在于“避免副作用”,不改变也不依赖当前函数外的数据。结合不可变数据、函数是第一等公民等特性,使函数带有自描述性,可读性较高。 面向对象编程的核心在于抽象,提供清晰的对象边界。结合封装、集成、多态特性,降低了代码的耦合度,提升了系统的可维护性。 不同的范式的出现,目的就是为了应对不同的场景,但最终的目标都是提高生产力。就如华山派的剑宗、气宗之别,剑宗认为“剑为主,气为辅”,而气宗则反之。每个范式都会有自己的”心法”,但最终殊途同归,达到至高境界后则是剑气双修。 | 小结 阅读完之前内容后,相信各位读者对编程范式有了初步的理解,那么接下来就和笔者一起来实现业务的真实需求。 | 需求 1.解析并收集shannon, fio 两种 flash卡的温度、寿命等信息。 2.对实现代码进行单元测试 在用过程式实现之前,笔者先给大家介绍下什么叫过程式编程。 | 过程式编程(Procedural) 过程式编程和面向对象编程的区别并不在于是否使用函数或者类,也就是说用到类或对象的可能是过程式编程,只用函数而没有类的也可能是面向对象编程。那么他们的区别又在哪儿呢? 面向过程其实是最为实际的一种思考方式,可以说面向过程是一种基础的方法,它考虑的是实际地实现。一般的面向过程是从上往下步步求精,所以面向过程最重要的是模块化的思想方法。当程序规模不是很大时,面向过程的方法还会体现出一种优势。因为程序的流程很清楚,按着模块与函数的方法可以很好的组织。 关键部分实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
def get_shannon_info(output): """获取shannon类型flash卡信息 """ def check_health(): time_left = float(sub_info["life_left"]) if time_left < DISK_ALARM_LIFETIME: message = "time left is less than {}%".format(DISK_ALARM_LIFETIME) return message temperature = float(sub_info["temperature"].split()[0]) if temperature > DISK_ALARM_TEMPERATURE: message = "temperature is over than {} C".format(DISK_ALARM_TEMPERATURE) return message return "healthy" result = {} all_info = _get_shannon_info(output) for info in all_info: sub_info = {} sub_info["available_capacity"] = info.get("disk_capacity", "") sub_info["device_name"] = info.get("block_device_node", "") sub_info["firmware_version"] = info.get("firmware_version", "") sub_info["interface"] = "PCIe" sub_info["life_left"] = str(info.get("estimated_life_left", "").replace("%", "")) sub_info["pcie_id"] = info.get("pci_deviceid", "") sub_info["pcie_length"] = "" sub_info["pcie_type"] = "" sub_info["physical_read"] = info.get("host_read_data", "") sub_info["physical_write"] = info.get("total_write_data", "") sub_info["serial_number"] = info.get("serial_number") sub_info["temperature"] = info.get("controller_temperature") sub_info["type"] = info["type"] sub_info["error_msg"] = check_health() sub_info["status"] = "ok" if sub_info["error_msg"] == "healthy" else "error" if sub_info["serial_number"]: result[sub_info["serial_number"]] = sub_info else: result[sub_info["device_name"]] = sub_info return result |
代码问题 1.逻辑冗长,局部修改必须阅读整段代码 2.对外部变量有依赖 3.内部存在共享变量 4.函数内部存在临时变量 测试代码 过程式的测试代码效果远不如函数式有效,过程式的实现逻辑过于冗长,导致测试效果并不够好。 | 函数式编程(Functional) 当谈论函数式编程,会提到非常多的“函数式”特性。提到不可变数据,第一类对象以及尾调用优化,这些是帮助函数式编程的语言特征。提到mapping(映射),reducing(归纳),piplining(管道),recursing(递归),currying(科里化),以及高阶函数的使用,这些是用来写函数式代码的编程技术。提到并行,惰性计算以及确定性,这些是有利于函数式编程的属性。 最主要的原则是避免副作用,它不会依赖也不会改变当前函数以外的数据。 声明式的函数,让开发者只需要表达 “想要做什么”,而不需要表达 “怎么去做”,这样就极大地简化了开发者的工作。至于具体 “怎么去做”,让专门的任务协调框架去实现,这个框架可以灵活地分配工作给不同的核、不同的计算机,而开发者不必关心框架背后发生了什么。 关键部分实现代码
1 2 3 4 5 6 7 8 9 10 11 12 |
def get_shannon_info(output): """查询shannon类型flash卡信息 """ lines = checks_string_split_by_function(output, is_shannon_flash_device) info = map(parser_shannon_info, lines) # map(lambda x: x.setdefault("type", "shannon"), info) for item in info: item["type"] = "shannon" data = map(modify_the_properties, info) return reduce(combining_data, map(convert_data_format, data)) |
以上代码带有自描述性,通过函数名就可知在做什么,这也是函数式的一个特性: 代码是在描述要干什么,而不是怎么干。 测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
@pytest.mark.parametrize("line, result", [ ("Found Shannon PCIE", False), ("Found Shannon PCIE Flash car", False), ("Found Shannon PCIE Flash card a", True), ("Found Shannon PCIE Flash card", True), ("Found Shannon PCIE Flash card.", True), ]) def test_is_shannon_flash_device(line, result): assert functional.is_shannon_flash_device(line) == result @pytest.mark.parametrize("line, result", [ ("a=1", True), ("b=2", True), ("c=2333", True), ("d x=abcde", True), ("Found Shannon PCIE=1", True), ("abcdedfew=", False), ("Found Shannon PCIE", False), (" =Found Shannon PCIE", False), ("=Found Shannon PCIE", False), ("Found Shannon PCIE=", False), ("Found Shannon PCIE= ", False), ]) def test_is_effective_value(line, result): assert functional.is_effective_value(line) == result @pytest.mark.parametrize("line, result", [ ("a=1", {"a": "1"}), ("b=2", {"b": "2"}), ("a=a", {"a": "a"}), ("abc=a", {"abc": "a"}), ("abc=abcde", {"abc": "abcde"}), ]) def test_gets_the_index_name_and_value(line, result): assert functional.gets_the_index_name_and_value(line) == result @pytest.mark.parametrize("output, filter_func, result", [ ("abcd\nbcd\nabcd\nbcd\naa\naa", lambda x: "a" in x, ["abcd\nbcd", "abcd\nbcd", "aa", "aa"]), (open(os.path.join(project_path, "fixtures", "shannon-status.txt")).read(), functional.is_shannon_flash_device, [ open(os.path.join(project_path, "fixtures", "shannon-sctb.txt")).read(), open(os.path.join(project_path, "fixtures", "shannon-scta.txt")).read() ]) ]) def test_checks_string_split_by_function(output, filter_func, result): assert functional.checks_string_split_by_function(output, filter_func) == result |
| 面向对象编程(Object-Oriented) 并不是使用类才是面向对象编程。如果你专注于状态改变和密封抽象,你就是在用面向对象编程。类只是帮助简化面向对象编程的工具,并不是面向对象编程的要求或指示器。封装是一个过程,它分隔构成抽象的结构和行为的元素。封装的作用是分离抽象的概念接口及其实现。类只是帮助简化面向对象编程的工具,并不是面向对象编程的要求或指示器。 随着系统越来越复杂,系统就会变得越来越容易崩溃,分而治之,解决复杂性的技巧。面对对象思想的产生是为了让你能更方便的理解代码。有了那些封装,多态,继承,能让你专注于部分功能,而不需要了解全局。 关键部分实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
class IFlash(six.with_metaclass(abc.ABCMeta)): def __init__(self): pass @abc.abstractmethod def collect(self): """收集flash卡物理信息 """ pass class FlashShannon(IFlash): """宝存的Flash卡 """ def __init__(self, txt_path, command, printer): super(FlashShannon, self).__init__() self.txt_path = txt_path self.command = command self.printer = printer def collect(self): result = {} for info in self._get_shannon_info(): life_left = str(info.get("estimated_life_left", "")).replace("%", "") temperature = info.get("controller_temperature", "") error_msg = self._get_health_message(life_left, temperature) sub_info = { "available_capacity": info.get("disk_capacity", ""), "device_name": info.get("block_device_node", ""), "firmware_version": info.get("firmware_version", ""), "interface": "PCIe", "life_left": life_left, "pcie_id": info.get("pci_deviceid", ""), "pcie_length": "", "pcie_type": "", "physical_read": info.get("host_read_data", ""), "physical_write": info.get("total_write_data", ""), "serial_number": info.get("serial_number", ""), "temperature": temperature, "type": info["type"], "error_msg": error_msg, "status": "ok" if error_msg == "healthy" else "error" } if sub_info["serial_number"]: result[sub_info["serial_number"]] = sub_info else: result[sub_info["device_name"]] = sub_info return result class FlashFio(IFlash): """fio的Flash卡 """ def __init__(self, txt_path): super(FlashFio, self).__init__() self.txt_path = txt_path def collect(self): disk_info = {} adapter_info = self._get_adapter_info() for info in adapter_info: serial_number = info["fio_serial_number"] for io in info["iomemory"]: data = self._combining_io_memory(io) data["serial_number"] = serial_number disk_info[serial_number] = data return disk_info |
| 编程范式带来的好处 范式就像武功心法,可以更快的练成绝世神功,但还是离不开基础功。代码也一样,通过遵循相关范式和良好的设计后,会带来可读性、扩展性和可维护性更好的代码,进而提升软件的质量。 | 总结 命令式编程、面向对象编程、函数式编程,虽然受人追捧的时间点各不相同,但是本质上并没有优劣之分。 面向对象和函数式、过程式编程也不是完成独立和有严格的界限,在抽象出各个独立的对象后,每个对象的具体行为实现还是有函数式和过程式完成。 现代的程序员应该很少有门派之见了,应该集百家之所长,学习其它范式(语言)的优秀设计理念,集成到自己的代码(产品、语言)中,提升工作效率。 | 致谢 简述编程范式:https://ginqi7.github.io/posts/brief-description-of-programming-paradigm.html 编程范型:https://zh.wikipedia.org/wiki/%E7%BC%96%E7%A8%8B%E8%8C%83%E5%9E%8B 学习编程之概述—从编程范式开始:http://dataunion.org/23223.html 面向对象编程 VS 函数式编程:http://blog.swanspace.org/oo_vs_fp/ […]
View Details泛型编程(Generic Programming)最初提出时的动机很简单直接:发明一种语言机制,能够帮助实现一个通用的标准容器库。 所谓通用的标准容器库,就是要能够做到,比如用一个List类存放所有可能类型的对象这样的事;泛型编程让你编写完全一般化并可重复使用的算法,其效率与针对某特定数据类型而设计的算法相同。泛型即是指具有在多种数据类型上皆可操作的含义,与模板有些相似。 STL巨大,而且可以扩充,它包含很多计算机基本算法和数据结构,而且将算法与数据结构完全分离,其中算法是泛型的,不与任何特定数据结构或对象类型系在一起。 from:https://baike.baidu.com/item/%E6%B3%9B%E5%9E%8B%E7%BC%96%E7%A8%8B/6787248?fr=aladdin
View Details