zoukankan      html  css  js  c++  java
  • 讲讲python“=”运算符上的优雅语法

    心路历程

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

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

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

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

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

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

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

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

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

      2、玩法1): 序列赋值

    if __name__ == "__main__":
        #name  = "蒋乐哥哥"
        #age   = "16"
        #major = "软件工程"
        #job   = "dba"
        name,age,major,job = "蒋乐哥哥","16","软件工程","dba"
        #是不是感觉自己平时不会这样写、也感觉不到这样写有什么好处、别急我们看一下它的变种 1
    
        name,age,major,job = ("蒋乐哥哥","16","软件工程","dba")
        #事实上这个变种是比较常用的,用于取出可迭代对象中的各个值、别急它还可以再变
    
        name,age,major,job,*ignore =("蒋乐哥哥","16","软件工程","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,*_ =("蒋乐哥哥","16","软件工程","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不要有过多的口音。

      

      

    ------

  • 相关阅读:
    七类网线 支持10gb/s的速度的计算方法
    Linux 压缩 解压缩 命令相关
    [至顶网] Win2019 发布 LTSC 10年支持期
    安装报错信息 改天找人帮忙看下.
    [学习]仿照cnblog 搭建 Oracle RAC 双节点 困.. 后续做不下去了..
    Windows 作为 openssl server端时的处理
    阿里云构建Kafka单机集群环境
    nginx解决跨域
    让网站永久拥有HTTPS
    ORA-01940: cannot drop a user that is currently connected 问题解析
  • 原文地址:https://www.cnblogs.com/JiangLe/p/8875654.html
Copyright © 2011-2022 走看看