心路历程

  之前学linux,虽然学的行算不错,不过总感觉差了点什么,自己找不到也说不出来;直到有一天我看到别人mount上了一个普通文件;

  当时给我的感觉这太不可思议了,这个文件又不是块设备;后来脑子里突然想到一句话“一切些文件”,一身的冷汉;原来这个就是linx

  的哲学它不是一句口号!它是linux这门武功的上乘心法。 linux我顿悟了。

  昨天夜里看python看到一句话“python语言最好的品质之一是一致性”;这种高度的一致性来自于哪里?我想应该是针对某一特定的

  问题在python中“最优解只有一个”的原因。

从赋值语句看语言的一致性:

  赋值语句每一门语言都有不过python真的是玩出了新的高度,下面上干货。

  1、常规赋值与其它语言没区别

if __name__ == "__main__":
name = "蒋乐哥哥"
age = ""
major = "软件工程"
job = "dba" print("{} ,{} ,{} ,{}".format(name,age,major,job))

  2、玩法1): 序列赋值

if __name__ == "__main__":
#name = "蒋乐哥哥"
#age = "16"
#major = "软件工程"
#job = "dba"
name,age,major,job = "蒋乐哥哥","","软件工程","dba"
#是不是感觉自己平时不会这样写、也感觉不到这样写有什么好处、别急我们看一下它的变种 1 name,age,major,job = ("蒋乐哥哥","","软件工程","dba")
#事实上这个变种是比较常用的,用于取出可迭代对象中的各个值、别急它还可以再变 name,age,major,job,*ignore =("蒋乐哥哥","","软件工程","dba","才华横溢","日进斗金","心地善良") print("name={} ,age={} ,major={} ,job={}".format(name,age,major,job))
print("ignore={}".format(ignore)) #输出如下:name=蒋乐哥哥 ,age=16 ,major=软件工程 ,job=dba
#输出如下:ignore=['才华横溢', '日进斗金', '心地善良']

  可以看到对于我们不关注的数据直接被*ignore接收了,但是高手之间出于对一致性的追求,通常不会用ignore这个变量,而是这样写

    name,age,major,job,*_ =("蒋乐哥哥","","软件工程","dba","才华横溢","日进斗金","心地善良")

    print("name={} ,age={} ,major={} ,job={}".format(name,age,major,job))
print("ignore={}".format(_))

  他们对于用不到的数据通常是给一个“_”变量来保存的;也许你还是感觉这面的写法没有意义,太学院派了;那么下面我们来写一个有意义

  的程序,用它来分析linux系统的/etc/passwd文件,这个文件保存的是linux中的用户信息,其中第一列是用户名,最后一列是这个用户对应

  的shell。我们这个程序的目的就是取出用户名和它对应的shell,下面是我电脑上的一份。

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:997:User for polkitd:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
uwsgi:x:1000:1000::/home/uwsgi:/bin/bash
nginx:x:1001:1001::/home/nginx:/bin/bash

  想好怎么写了吗?我的代码输出是这样的

python3 main.py
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
mail /sbin/nologin
operator /sbin/nologin
games /sbin/nologin
ftp /sbin/nologin
nobody /sbin/nologin
systemd-network /sbin/nologin
dbus /sbin/nologin
polkitd /sbin/nologin
postfix /sbin/nologin
sshd /sbin/nologin
chrony /sbin/nologin
uwsgi /bin/bash
nginx /bin/bash

  然而我的代码是这样的

if __name__=="__main__":
with open('/etc/passwd') as passwd:
for line in passwd:
name,*_,shell = line.split(':')
print(name,shell,end='')

  上面的代码只是活用了Python的“赋值”代码量就大大减少了。

  3、玩法2): 参数传递

  参数传递也是“赋值”的另一种形式,但是这两种形式是统一的;下面也用一个学院派的例子来举例。假设我们有如下记录

    oprations = [
('add',1,2),
('add',2,3),
('sub',3,2),
('sub',1,1)
]

  第一个字段代表要执行的操作,后面两个字段是操作的参数;也就是说第一个记录的意思就是计算1+2,第三条记录的意思就是计算3-2;

  写个加减法并不难! 先来看一下代有C#口音的写法

def add(a,b):
print("{} + {} = {} ".format(a,b,a+b)) def sub(a,b):
print("{} - {} = {} ".format(a,b,a-b)) if __name__ == "__main__":
oprations = [
('add',1,2),
('add',2,3),
('sub',3,2),
('sub',1,1)
]
for op in oprations:
if op[0]=='add':
add(op[1],op[2])
elif op[0]=='sub':
sub(op[1],op[2])

  看起来没有什么问题,型参通过对op[]索引操作来完成,想想这是天经地义的;看一下pythonic的写法吧

def add(a,b):
print("{} + {} = {} ".format(a,b,a+b)) def sub(a,b):
print("{} - {} = {} ".format(a,b,a-b)) if __name__ == "__main__":
oprations = [
('add',1,2),
('add',2,3),
('sub',3,2),
('sub',1,1)
] for op,*args in oprations:
if op =='add':
add(*args)
elif op =='sub':
sub(*args)

  后都更加的“优雅”,“灵活”;优雅源自于不要再去关心索引,而是直接就能看出参数是怎么传递的;灵活吗?我们再调整一下需求

  “要求add,sub支持三个数据相加减,或两个数据相加减”

def add(a,b,c=0):
print("{} + {} + {} = {} ".format(a,b,c,a+b+c)) def sub(a,b,c=0):
print("{} - {} - {} = {} ".format(a,b,c,a-b-c)) if __name__ == "__main__":
oprations = [
('add',1,2,1),
('add',2,3),
('sub',3,2,1),
('sub',1,1)
] for op,*args in oprations:
if op =='add':
add(*args)
elif op =='sub':
sub(*args)

  由于pythonic的方式并没有用到索引,所以在调用方完全不要改,只要改一下sub和add的定义就好了,就能同时直接两参数,三参数了;

  而使用索引是做不到的!所以呀编码的时候要尽可能的pythonic不要有过多的口音。

  

  

------

讲讲python“=”运算符上的优雅语法的更多相关文章

  1. Python运算符,python入门到精通[五]

    运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算.例如:2+3,其操作数是2和3,而运算符则是“+”.在计算器语言中运算符大致可以分为5种类型:算术运算符.连接运算符.关系运算符.赋值运 ...

  2. Python 运算符与数据类型

    Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...

  3. Python之介绍、基本语法、流程控制

    本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表达式if ...else语 ...

  4. Python入门(上)

    Python入门(上) Python入门(上) 简介 Python 基础语法 行与缩进 注释 运算符 标准数据类型 变量 编程流程 顺序(略) 分支 if 循环 for while break 和 c ...

  5. python运算符与数据类型

    python运算符 Python语言支持以下类型的运算符: 算术运算符 比较(关系)运算符 赋值运算符 逻辑运算符 位运算符 成员运算符 身份运算符 运算符优先级 以下假设变量: a=10,b=20: ...

  6. 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)

    本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上?             成员函数可以被看作是类 ...

  7. Python中的相对导入语法

    Python中支持相对导入语法,即可以相对于某一个package进行导入,具体语法如下: # 导入"./dir2/spam.py", .表示当前目录 from .dir2 impo ...

  8. Python项目中如何优雅的import

    Python项目中如何优雅的import 前言 之前有一篇关于Python编码规范的随笔, 但是写的比较杂乱, 因为提到了import语句, 在篇文章中, 我专门来讲Python项目中如何更好的imp ...

  9. Python运算符及逻辑运算

    基本运算符 运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算.例如:2+3,其操作数是2和3,而运算符则是“+”.在计算器语言中运算符大致可以分为5种类型:算术运算符.连接运算符.关系运 ...

随机推荐

  1. 获取自增ID

    方法一(一般不使用,多线程可能不准确) SELECT MAX(id) FROM table 方法二(一般使用这个) SELECT LAST_INSERT_ID()

  2. JAVA遍历HashMap和ArrayList

    List Map 基础信息 HashMap 最近写程序经常需要遍历集合,所以总结一下内容: 一.简单实现 Map map = new HashMap(); for(Object o : map.key ...

  3. TCP三次握手详解

    当两台主机采用 TCP 协议进行通信时,在交换数据前将建立连接.通信完成后,将关闭会话并终止连接.连接和会话机制保障了TCP 的可靠性功能. 请参见图中建立并终止 TCP 连接的步骤. 主机将跟踪会话 ...

  4. AndroidStudio不自己主动加入新创建的文件到VCS

    从远程仓库下载了一份源代码,版本号控制是用的SVN.但发现了一个问题.改动和删除文件时,版本号管理都有记录. 可是假设我新建一个文件时.却发现没有自己主动关联到VCS,也不能手动加入到VCS中,这样我 ...

  5. 操作系统动态内存管理——malloc和free的工作机制

    动态内存分配 就 是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法. malloc()是C语言中动态存储管理 的一组标准库函数之一.其作用是在内存的动态存储区中分配一个长度为size的 ...

  6. Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node ……

    解决办法是加一个等待时间即可解决问题: setTimeout(function () { you code }, );

  7. java并发之SynchronousQueue实现原理

    前言 SynchronousQueue是一个比较特别的队列,由于在线程池方面有所应用,为了更好的理解线程池的实现原理,笔者花了些时间学习了一下该队列源码(JDK1.8),此队列源码中充斥着大量的CAS ...

  8. qt坐标系统与布局的简单入门

     qt坐标系统 qt坐标系统比較简单 ); 上面的代码把button显示为父窗体的20,20处宽度为100,高度为100 接下去是布局 qt里面布局须要增加<QLayout.h>这个头 ...

  9. django之创建第7-2个项目-url配置分离

    1.urls.PY分离 # -*- coding: UTF-8 -*- from django.conf.urls import patterns, include, url # Uncomment ...

  10. HDU 1069 Monkey and Banana(最大的单调递减序列啊 dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1069 Problem Description A group of researchers are d ...