优雅的函数

    • argparse库
      • 摘要
      • 入门
    • 优雅的函数
      • 完整小例子
    • 用途
      • 套接字编程时的运用
    • 总结

近来在观摩一些开源脚本的时候,发现了一个比较神奇的关于命令行运行脚本编写的小技巧, 特来做下记录。


argparse库

前段时间对argparse进行了浅尝辄止,蜻蜓点水式的学习,感觉自己会用了,然后就没有对其进行更加深入的学习,而通过阅读别人的代码,发现自己对于这个东西并没有真正的领悟。

在阅读GitHub上相关脚本的代码的时候,往往会有这样的效果。总是会有那么些个脚本,让你眼前一亮。然后情不自禁的反思自己这方面的欠缺。

我觉得这又何尝不是一个查漏补缺的学习方式呢。哈,有点跑偏了。下面开始进入正题。

摘要

想必作为一个程序员,或多或少的都会使用到命令行。即使是使用Windows操作系统的人,也很有可能会接触到一些命令行。比如查看一下自己的笔记本在当前局域网内的IP地址。

从图中也不难发现,命令后面跟了一些参数,还进行了一些组合(管道命令的使用), Linux命令行的艺术更为神奇,但不在讨论范围内,这里不过多叙述了。

如此,想让自己的程序也能有这样神奇的表现,那么添加参数就会是一个很好的选择。幸运的是Python让着一个魔法的实现变得更加的容易了。答案之一就是argparse

入门

对于argparse,也不要想得过于高深。其功能就是解析我们输入的命令,并正确地为相关的参数赋予相匹配的值。仅此而已。下面看一个简单的小例子来入门。

import argparse
parser = argparse.ArgumentParser(description='You can use -h option to see the details of this application')

args = parser.parse_args()
print args

观察代码和运行结果,不难发现。argparse帮助我们把参数正确的赋予给了一个类对象Namespace。然后为其属性进行了赋值操作。然后在脚本中就可以使用这些属性作为我们代码运行所需参数的实参值啦。

关于argparse更多细节的使用,可以参照博主下面的这篇文章。
argparse 使用详解

优雅的函数

在Python中,一切皆为对象。也就是说,不管是类还是字符串,都是对象。其实函数也是一个对象,甚至是表示类的类型的这个类型,也是一个对象,这一点可以在Python源码中详细的看到。

关于优雅这一个特性,先来看个小测试。

不难发现,函数function可以作为字典中某一个键的值。然后str_function就相当于是function的一个别名,复制了function函数,然后我们就可以像调用function函数一样随意的调用str_function函数了。

那么下面再来看个小例子,使用字符串会怎么样呢?

报错了。那么仔细的思考一下,为什么会出现这个问题呢?

回归代码上,function本身就是一个函数,被Python解释器事先得到了。然后对于字典对象,键值对中的值可以是任何值,所以可以将function作为值传过来。而且其仍然会是一个函数。

相反,使用字符串的话,string引用的仍然只会是一个字符串。所以不可能被解释为一个函数的,原本的特性就决定了会出现这个结果。

可能您会觉得这种问题,亦或是这种代码很低智,但是很多时候,对于基础不甚清楚的话,就很有可能会犯这样的错误。尤其是对脚本语言,没有编译层面的检查,问题出现的就可能会更更加的频繁。

完整小例子

下面使用一个完整的小例子,作为总结。可以仔细的思考一下代码运行结果下的原理。以及优雅的函数的优雅的特性到底表现在哪里。

# coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
#    __author__ = '郭 璞'
#    __date__ = '2016/11/26'
#    __Desc__ = 优雅的函数
import argparse

def func1(param):
    print "Func1 is assembled Successfully and the parameter can be setted as {param}".format(param=param)

def func2(param):
    print "Func2 is assembled Successfully and the parameter can be setted as {param}".format(param=param)
if __name__ == "__main__":
    choices = {
        'func1': func1,
        'func2': func2,
    }

    parser = argparse.ArgumentParser(description='You can use -h option to see the details of this application')
    parser.add_argument('choice',choices=choices, help='you can choose one of the parameter you want, func1, or func2' )
    parser.add_argument('-p', type=int, help='the value you want to attach to the function you want to run.')
    args = parser.parse_args()

    print type(args)
    print args
    print args.choice, args.p
    function = choices[args.choice]
    function(args.p)

用途

关于优雅的函数的这一个特性,其实被运用到的地方有很多。最为常用的就是让用户来决定脚本的运行方式。尤其是脚本中有相似的函数结构,但是功能完全不同的时候会更更加的实用。

比如说,套接字实现服务器端以及客户端的时候,需要的参数大致是相当的(不同的部分,可以使用argparse的add_argument方法进行额外的指定)。编写脚本的时候就可以考虑写到一个脚本中,这样更能体现二者的相似性以及不同点,对套接字有更加深刻的认识。

套接字编程时的运用

import argparse, socket
from datetime import datetime

MAX_BYTES = 65535

def server(port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind(('127.0.0.1', port))
    print 'Listening at {}'.format(sock.getsockname())
    while True:
        data, address = sock.recvfrom(MAX_BYTES)
        text = data.decode('ascii')
        print 'the client at {} says {!r}'.format(address, text)
        text = 'your data was {} bytes long!'.format(len(data))
        data = text.encode('ascii')
        sock.sendto(data, address)

def client(port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    text = 'the time is {}'.format(datetime.now())
    data = text.encode('ascii')
    sock.sendto(data, ('127.0.0.1', port))
    print 'the OS assigned me the address {}'.format(sock.getsockname())
    data, address = sock.recvfrom(MAX_BYTES)
    text = data.decode('ascii')
    print 'The server replied {!r}'.format(address, text)

if __name__ == '__main__':
    choices = {
        'client': client,
        'server': server
    }
    parser = argparse.ArgumentParser(description='send and receive UDP locally!')
    parser.add_argument('role', choices=choices, help='which role to play')
    parser.add_argument('-p', metavar='PORT', type=int, default=1060, help='UDP port (default 1060)')

    args = parser.parse_args()
    function = choices[args.role]
    function(args.p)

这样,运行脚本的时候,就可以有选择性咯。

总结

关于如何优雅的实现运行一个函数,这里涉及的简直如冰山一角。

要想学到更多,还是得多阅读高质量的代码。庆幸的是,GitHub给我们提供了这样的一个很好的平台。

时间: 2024-09-25 07:34:42

优雅的函数的相关文章

使用匿名函数减少重复代码

在一个项目中我使用到了软件工厂的工具帮助生成了对数据库的CRUD的方法,在Logic中需要对数据层进行封装,以提供对实体操作的接口,封装后的代码如:   public  bool AddNews(News news) {     try     {         newsRep.Add(news);//执行数据库操作        return true;     }     catch (Exception ex)     {         LogLogic.AddSystemLog(th

Hugo探究

朋友介绍了一个开源项目Hugo,国庆期间,我对它进行了一些学习和探究. Hugo介绍 我们写代码时,常会打日志输出某个函数执行耗时,传入的参数以及返回值.那么我们能否把这件事情做的更加优雅呢?Hugo就是为此而设计的. 你只需要在需要监控的函数上加上@DebugLog注解,函数运行时就会自动输出上面提到的信息. 例如: @DebugLog public String getName(String first, String last) { SystemClock.sleep(15); // Do

Koa框架教程,Koa框架开发指南,Koa框架中文使用手册,Koa框架中文文档

我的博客:CODE大全:www.codedq.net:业余草:www.xttblog.com:爱分享:www.ndislwf.com或ifxvn.com. Koa -- 基于 Node.js 平台的下一代 web 开发框架. 简介 koa 是由 Express 原班人马打造的,致力于成为一个更小.更富有表现力.更健壮的 Web 框架.使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率.koa 不在内核方法中绑定任何中间

讨喜的隔离可变性(四)收发消息

我们可以向角色发送任何类型的消息--String.Integer.Long.Double.List.Map.元组(tuples).Scala的case类-但其中有一点需要注意的是,上述所有类型的消息都必须是不可变的.在上述这些类型中,我对于元组有着特殊的偏好,这并非因为我听到别人把元组误读成"two-ples"时感到很有趣,而是由于元组是轻量的.不可变的并且是最容易创建的实例之一.例如,在Scala中,我们可以简单地用(number1,number2)来创建一个含有两个数字的元组.除了

《JavaScript设计模式》——9.9 Facade(外观)模式

9.9 Facade(外观)模式 当创建外观时,向外界展示的外表可能掩盖了一个非常不同的现实.这是我们下一个要查看的模式名称的灵感来源-Facade模式.Facade模式为更大的代码体提供了一个方便的高层次接口,能够隐藏其底层的真实复杂性.可以把它想成是简化API来展示给其他开发人员,通常都是可以提高可用性(见图9-8). Facade是一种结构型模式,在jQuery等JavaScript库中经常可以看到,尽管一个实现可能支持具有广泛行为的方法,但却只有一个"外观"或这些方法的有限抽象

解析PHP无限级分类方法及代码_php技巧

无论你要构建自己的论坛,在你的网站上发布消息还是书写自己的CMS程序,你都会遇到要在数据库中存储层次数据的情况.同时,除非你使用一种像XML的数据库,否则关系数据库中的表都不是层次结构的,他们只是一个平坦的列表.所以你必须找到一种把层次数据库转化的方法. 存储树形结构是一个很常见的问题,他有好几种解决方案.主要有两种方法:邻接列表模型和改进前序遍历树算法 在本文中,我们将探讨这两种保存层次数据的方法.我将举一个在线食品店树形图的例子.这个食品店通过类别.颜色和品种来组织食品.树形图如下: 本文包

Node.js的Koa框架上手及MySQL操作指南_node.js

由 Express 原班人马打造的 koa,致力于成为一个更小.更健壮.更富有表现力的 Web 框架.使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升常用错误处理效率.Koa 不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手. 安装koakoa 依赖支持 generator 的 Node 环境,也就是说,node的版本要在 0.11.9 或者更高,否则将无法执行. 用npm: $

Kotlin 简单优雅的高阶函数

Kotlin 简单优雅的高阶函数 最新上架!!!< Kotlin极简教程> 陈光剑 (机械工业出版社) 可直接打开京东,淘宝,当当===> 搜索: Kotlin 极简教程http://www.jianshu.com/p/35b487734339 函数代表一种关系 f 的蕴涵逻辑流.这种蕴涵逻辑流,其实就是映射(Mapping). 一切皆是映射. 我们说组合是编程的本质,其实,组合就是建立映射关系. 我们说, 程序 = 算法+数据结构 我们把程序看做图论里面的一张图G,这里的数据结构就是图

函数中使用require_once问题深入探讨 优雅的配置文件定义方法推荐_php实例

背景 在项目中很多人喜欢在配置文件使用数组来配置各个配置项,如等级的配置level.config.php: 复制代码 代码如下: <?php $g_levelConfig = array(                     '1'=>'新手',                     '2'=>'进阶',                 ); 因为项目不同模块经常会相互调用方法,会出现重复包含一个文件的情况,为了避免错误,大家一般都会用require_one,而且经常会在函数里包含