希望系统性学习一门编程语言的朋友请关注我,本专栏后续会持续分享优质文章。
本篇为第五篇介绍Python知识的文章,本篇也开始接触到该门语言的逻辑语法部分,这一部分在编程语言中使用很广泛,小到一段语句,大到一个模块里面都有很多逻辑判断语句,所以很有必要细致的去理解它,并将他的一些常用格式熟记于心,好了开始我们下面的文章。
本节主要编写的为Python语句中if语句的编写要求:
>>>
>>> if 1 > 2:
... print('a')
... else:
... print('b')
...
b
>>>
本段程序为一个简单的 if...else 语句,这个语句主要是进行二个数做大小的判断,得出的结果为一个bool值,if语句在bool值为True时执行打印字符a,为False时执行打印字符b,通过这样一段代码我们就可以大概的看到if语句的执行条件,执行过程等情况。
针对 if 结构语言本专栏做了以下细致的总结,大家可以细致的体会其语法作用。
if语句的基本语法如下所示:
if condition:
# 如果条件为True,则执行这里的代码块
# 可以有多行代码
else:
# 如果条件为False,则执行这里的代码块
# 可以有多行代码
在if语句中,condition是一个表达式,可以是返回True或False的任何东西。
常见的比较运算符包括:
多个条件:
你也可以使用逻辑运算符组合多个条件:
单向分支结构:
if <条件表达式>:
执行语句
...
双向分支结构:
if <条件表达式>:
执行语句
...
else:
执行语句
...
多分支结构:
if <条件表达式>:
执行语句
...
elif <条件表达式>:
执行语句
...
else:
执行语句
...
存在多个elif语句时,Python会按照顺序逐个检查每个条件,执行第一个满足条件的代码块,然后跳过其他条件的检查。如果前面的elif条件满足了,那么后面的elif语句就不会再被执行。
嵌套分支结构:
if <条件表达式>:
if <条件表达式>:
执行语句
...
else:
执行语句
...
else:
if <条件表达式>:
执行语句
...
else:
执行语句
...
注意:每一层的缩进格式要统一,否则可能会导致意想不到的情况。
让优质的技术更自由、开放的传播,我是「技术小剑客」欢迎你的关注和留言。
介: 和大家一起探讨一下优雅代码
谈到好代码,我的第一想法就是优雅,那我们如何该写出好的代码,让阅读的人感受到优雅呢?首先简单探讨一下优雅代码的定义
关于好代码的定义,各路大神都给出了自己的定义和见解
首先要达成一致,我们写的代码,除了用于机器执行产生我们预期的效果之外,更多的时候是给人读的,可能是后续的维护人员,更多时候是一段时间后的作者本人,因此优雅面向不同的用户有两层含义的解读
这次,我们就来聊一聊,什么代码是优雅的代码,怎样写出优雅的代码
简单说就是类、方法、变量的命名要名副其实,要能描述清晰自己的职责。一个好的命名能输出更多的信息,它会告诉你,它为什么存在,它是做什么事的,应该怎么使用。一个简单的衡量标准是,如果命名完仍需要注释来补充语义,那就不是名副其实;
选个好名字要花时间,但省下的时间的时间比花掉的多,一旦发现有更好的名称,就换掉旧的。
举个栗子
public List<int[]> getItem() {
List<int[]> list1=new ArrayList<int[]>();
for (int[] x: theList)
if (x[0]==4)
list1.add(x);
return list1;
}
整体逻辑没啥问题,读完之后,就有很多问题在脑海中产生
代码应该体现所处的情景,比方说上述的代码所处情景是我们正在开发一种扫雷游戏,盘面是名为theList的单元格列表,那就将其名称改为gameBoard。
盘面上每个单元格都用一个简单数组表示。零下标条目是一种状态值,而这种状态值为4代表“已标记”。只要改为有意义的名称,代码就得到了改进。
更进一步,不用int数组来表示单元格,而是另写一个类。该类包括一个名副其实的函数(称为isFlagged),从而掩盖住哪个魔术数4,得到新的函数版本。
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells=new ArrayList<Cell>();
for (Cell cell : gameBoard)
if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
实际上,只要我们的代码有足够的表达力,能清晰的通过命名来做到名副其实,就不太需要注释,或者根本不需要;注释的存在往往是弥补我们无法用代码清晰表达意图的情况。可以想象一下,每次自己发现需要写注释的时候,是什么心态,担心此处代码明天自己看不懂或者别人看不懂,那有没有考虑用更好的语义的代码来替代。
但尽管有注释,也有好有坏,有时候注释也会撒谎,通常注释存在的越久,就离其描述的代码越远,变得越来越离谱;因为代码在变动在迭代,在注释和代码间可能会插入新的代码,旧代码我们通常copy来copy去,分离又重组,但注释一般不会修改,就会造成注释和描述的代码分离,对阅读者造成更大的迷惑。
我们在需要写注释的时候就要告诉自己,能不能用代码来进行描述。以下是一些坏代码的注释bad case
1. 一些被注释掉的代码
//something code
//something code
2. 位置标记
//begin
someting code;
//end
3. 签名标记
/** add by xiaoli*/
4. 非公用方法的javadoc
/**
* doSomething
*/
private void doSomething(){
}
5. 日志式注释
/** add xx
* update sometimes
* update sometimes
* update sometimes
*/
6. 误导性注释
//此处怎样xx
方法应该有多短小?没有明确约束,idea也不会限制你,但通常我们的方法不该长于一屏,至少多于一屏或者横向外溢到屏幕以外最直观的就会造成可读性体验差,读了下面忘记上面,左右拖拽等。对大多数笔记本来说一屏大概就30行左右。短小精简的方法要比30行短很多,比如
public String renderPageWithSetupAndTeardowns(Page page, boolean isSuite) throws Exception{
if(isTestPage(page)){
includeSetupAndTeardownPages(page,isSuite);
}
return page.getHtml();
}
if语句、else语句、while语句等,其中的代码应该只有一行,
改行通常是一个调用语句,这样不但能保持短小,还可以给调用方法命名一个有说明性的名字,进一步增加代码的可读性
一事精,便可动人。这个普世法则甚至适用于各种场合。像设计原则的单一职责模式,让类只有一个职责。如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致逻辑混乱,设计耦合。当一个职责发生变化时,可能会影响其它的职责。
另外,多个职责耦合在一起,会影响复用性。针对方法而言更是如此。方法作为程序的原子单元,保持单一会有效提升复用性。 那怎么判断一个方法是否只做了一件事。最简单的规则就是看看该方法是否能在拆出一个方法,且拆出去的方法是不同于该方法的诠释和实现。但是要注意同一方法的逻辑层级务必要一致。
抽象层级一致也是对方法只做一件事的更高要求,抽象层级不一致的代码一定是做了多件事。
我们读代码通常是自顶向下阅读,我们想让每个方法后面都跟着位于下一层级的方法,这样我们可以依着抽象层级向下阅读了。我们也需要这样阅读代码,先有整体在展示细节,这种叫向下规则。这也是保持方法短小,确保只做一件事的诀窍。一旦方法中混杂不同的抽象层级,会让人很迷惑,因为没办法这个方法中判断某个表达式是基础概念还是细节,更恶劣的是,一旦细节与基础概念混杂,更多的细节就会纠缠不清,举例子我们想写一个冰冻大象的需求
//把大象装进冰箱
public void frozenElephant(){
//1. 捕捉大象
//2. 运输大象
//3. 打开冰箱
//4. 放入大象
//5. 关闭冰箱
}
这个例子的1.2两步就不是一个层级的逻辑,是属于更高层级的抽象。3.4.5都是将大象放入冰箱的步骤,属于低层级的抽象。可以将代码拆分为如下实现,将高抽象层级的代码聚合提取出来,细节在分别单独实现,如下
public void frozenElephant(){
//1. 捕捉大象
catchElephant();
//2. 运输大象
transportElephant();
//将大象放入冰箱
putElephantInRefrigerator();
}
public void catchElephant(){
}
public void transportElephant(){
}
public void putElephantInRefrigerator(){
//打开冰箱
//放入大象
//关闭冰箱
}
针对错误码的判断会导致更深层次的嵌套结构,返回错误码就意味着要求调用者跟着处理错误,如下
if(deletePage()==OK){
if(registry.deleteReference(page.name)==OK){
if(configKeys.deleteKey(page.name.makeKey)==OK){
logger.log("page deleted")
}else{
logger.log("configKey not deleted")
}
}else{
logger.log("deleteReference from registry failed")
}
}else{
logger.log("delete failed")
return Error;
}
一般我们还需要将try/Catch代码块给抽离出去,另外形成方法。防止代码块过多搞乱代码结构,分不清错误处理还是正常流程。同时因为方法只做一件事,错误处理就是一件事,因此错误处理的方法不应该在做其他事,也就是如果一个方法中有try关键字,那try就是方法的开头。catch/finally代码块后面也不应该再有内容,如下
try{
deletePage(page);
registry.deleteReference(page.name);
configKeys.deleteKey(page.name.makeKey);
}catch(Exception e){
logger.log(e.getMessage());
}
比如Lombok组件通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法 举例如下:
比如Apache Commons系列组件给我们提供了关于字符串、集合、IO操作等工具方法。这些组件是个大宝库,提供了不少轮子
beanUtils | JavaBean进行各种操作,克隆对象、属性等等 |
codec | 处理常用的编码方法的工具类包,例如DES、SHA1、MD5、Base64等. |
collections | java集合框架操作 |
configuration | java应用程序的配置管理类库 |
io | io工具的封装 |
lang | Java基本对象方法的工具类包 如StringUtils、ArrayUtils等等. |
logging | 提供的日志接口 |
net | 提供了客户端和服务器端的数据验证框架 |
重构是对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
在重构之前一定要知道,一旦开始对类和方法进行重构,就需要事前有完备的单元测试用例来保障重构的准确性,每次重构之后都要去执行对应的单元测试用例,验证重构的正确性!
如果在一个以上的地点看到相同的代码结构,可以肯定的是,想办法抽线出来合而为一,代码会变得更好。一般包含几个点的重复
遵循这样一条原则:每当感觉需要以注释来说明点什么的时候,就把需要说明的东西写进一个独立函数中,并以其用途(而非实现手法)命名,可以对一组甚至短短一行代码做这件事。哪怕替换后的函数调用动作比函数自身还长,只要函数名称能够解释其用途,就要毫不犹豫地那样做,关键不在于函数的长度,而在于函数“做什么”和“如何做”之间的语义距离。
对数据的修改经常导致出乎意料的结果和难以发现的bug。在一处更新数据,却没有意识到软件中的另一处期望着完全不同的数据,于是出现难以预料的bug,往往比较难排查(需要排查数据流转的整体链路),这就需要一些方法用于约束对数据的更新,降低数据可变性的风险。
所谓模块化,就是力求将代码分出区域,最大化区域内部的交互、最小化跨区域的交互。但是经常出现一个函数跟另一个模块中的函数或者数据交流格外频繁,远胜于与所处模块内部的交流,这就是模块功能不单一的典型情况。
点击查看原文,获取更多福利!
https://developer.aliyun.com/article/1117703?utm_content=g_1000366324
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
、流程控制
1. 作用:控制代码的执行顺序
2. 分类
2.1顺序结构:从上到下依次执行代码语句
2.2选择结构:
1. if语句
简单if结构
if(条件表达式){
表达式成立时执行的代码段
}
注意 : 除零值以外,其他值都为真,以下条件为假值false
if(0){}
if(0.0){}
if(""){} //空字符串
if(undefined){}
if(NaN){}
if(null){}
特殊写法 : { }可以省略,一旦省略,if语句只控制其后的第一行代码
2. if - else结构:
if(条件表达式){
//条件成立时执行
}else{
//条件不成立时选择执行
}
3.多重分支结构:
if(条件1){
//条件1成立时执行
}else if(条件2){
//条件2成立时执行
}else if(条件3){
//条件3成立时执行
}...else{
//条件不成立时执行
}
2. switch语句:
语法 :
switch(value){
case 值1 :
//value与值1匹配全等时,执行的代码段
break; //结束匹配
case 值2 :
//value与值2匹配全等时,执行的代码段
break;
case 值3 :
//value与值3匹配全等时,执行的代码段
break;
default:
//所有case匹配失败后默认执行的语句
break;
}
使用时要注意的:
1. switch语句用于值的匹配,case用于列出所有可能的值;只有switch()表达式的值与case的值匹配全等时,才会执行case对应的代码段
2. break用于结束匹配,不再向后执行;可以省略,break一旦省略,会从当前匹配到的case开始,向后执行所有的代码语句,直至结束或碰到break跳出
3. default用来表示所有case都匹配失败的情况,一般写在末尾,做默认操作
4. 多个case共用代码段
case 值1:
case 值2:
case 值3:
//以上任意一个值匹配全等都会执行的代码段
3.循环结构:
作用 根据条件,重复执行某段代码
1. while循环:
定义循环变量;
while(循环条件){
条件满足时执行的代码段
更新循环变量;
}
2. do-while循环:
do{
循环体;
更新循环变量
}while(循环条件);
while 与do-while循环的区别 :
while 循环先判断循环条件,条件成立才执行循环体
do-while 循环不管条件是否成立,先执行一次循环体
3. for 循环
for(定义循环变量;循环条件;更新循环变量){
循环体;
}
循环控制 :
break 强制结束循环
continue 结束当次循环,开始下一次循环 循环嵌套 : 在循环中嵌套添加其他循环
二、函数
函数的作用:封装一段待执行的代码
语法:
//函数声明
function 函数名(参数列表){
函数体
return 返回值;
}
//函数调用
函数名(参数列表);
使用: 函数名自定义,见名知意,命名规范参照变量的命名规范。普通函数以小写字母开头,用于区分构造函数(构造函数使用大写字母开头,定义类)
三,匿名函数
匿名函数:省略函数名的函数。
语法为:
匿名函数自执行
(function (形参){
})(实参);
定义变量接收匿名函数:
var fn=function (){};
fn(); //函数调用
四,作用域
JavaScript 中作用域分为全局作用域和函数作用域,以函数的{ }作为划分作用域的依据
1,全局变量和全局函数
只要在函数外部使用 var 关键字定义的变量,或函数都是全局变量和全局函数,在任何地方都可以访问
所有省略 var 关键字定义的变量,一律是全局变量
2,局部变量/局部函数
在函数内部使用 var 关键字定义的变量为局部变量,函数内部定义的函数也为局部函数,只能在当前作用域中使用,外界无法访问
3,作用域链 局部作用域中访问变量或函数,首先从当前作用域中查找,当前作用域中没有的话,向上级作用域中查找,直至全局作用域
作者:YJ-TX
原文:https://www.cnblogs.com/yjtxin/p/12969576.html
*请认真填写需求信息,我们会在24小时内与您取得联系。