天天看點

argument和parameter的差別:

argument和parameter的差別:

其實跟今天的主題沒多大關系, 順便說一下, 因為看一些英文的技術文章, 會經常用這兩個概念.

parameter就相當于java裡的"形參":

方法/函數定義時在括号裡的參數

def explain_param_vs_arg(param1, param2):
        print param1, param2 
           

argument就是所謂"實參":

調用方法/函數時括号裡的參數

explain_param_vs_arg("arg1", "arg2")
           

Positional arguments:

例子:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo")
args = parser.parse_args()
print args.echo
           

輸出:

$ python prog.py
usage: prog.py [-h] echo
prog.py: error: the following arguments are required: echo

$ python prog.py --help
usage: prog.py [-h] echo

positional arguments: 
  echo
optional arguments: 
  -h, --help show this help message and exit

$ python prog.py foo
foo
           

上面的例子,基本沒什麼用. 來個有用點的:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
print args.echo
           

輸出:

$ python prog.py -h
usage: prog.py [-h] echo

positional arguments:
   echo     echo the string you use here

optional arguments:
 -h, --help       show this help message and exit
           

加了help參數之後, -h就加了對echo這個參數的說明.

來個更有用點的:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number")
args = parser.parse_args()
print args.square**2
           

輸出:

$ python prog.py 4
Traceback (most recent call last):
 File "prog.py", line 5, in <module>
   print args.square**2
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
           

結果不太理想. 是因為argparse把我們給的參數認成了string. 我們得告訴TA把square當成int來處理:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number",
                                   type=int)
args = parser.parse_args()
print args.square**2
           

運作結果:

$ python prog.py 4
16
$ python prog.py four
usage: prog.py [-h] square
prog.py: error: argument square: invalid int value: 'four'
           

這把就對了. 如果參數非法了還會報錯.

Optional arguments

前面介紹了positional arguments. 接下來我們看看optional arguments:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbosity", help="increase output verbosity")
args = parser.parse_args()
if args.verbosity:
  print "verbosity turned on"
           

輸出:

$ python prog.py --verbosity 1
verbosity turned on
$ python prog.py
$ python prog.py --help
usage: prog.py [-h] [--verbosity VERBOSITY]

optional arguments:
 -h, --help                      show this help message and exit
 --verbosity VERBOSITY
                                 increase output verbosity
$ python prog.py --verbosity
usage: prog.py [-h] [--verbosity VERBOSITY]
prog.py: error: argument --verbosity: expected one argument
           

看看都發生了什麼:

  • 這段代碼是想在--verbosity被指派的時候顯示點什麼, 沒被指派的時候什麼都不顯示.
  • 所謂optional arguments, 取意譯就是"選擇性參數". 我們可以看到當不使用--verbosity的時候是不會報錯的. args.verbosity的值也是None
  • help資訊也顯示有點不一樣. 加了[--verbosity VERSOSITY].
  • 當我們使用--verbosity的時候, 就要給TA賦個值, 否則會報錯.

上面的例子可以接受任意的整數作為

--verbosity

的值, 但對我們這簡單的小程式來說, 隻有倆個值是有用的, True或者False. 我們改一下:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbose", help="increase output verbosity",
                    action="store_true")
args = parser.parse_args()
if args.verbose:
    print "verbosity turned on"
           

輸出:

$ python prog.py --verbose
verbosity turned on
$ python prog.py --verbose 1
usage: prog.py [-h] [--verbose]
prog.py: error: unrecognized arguments: 1
$ python prog.py --help
usage: prog.py [-h] [--verbose]

optional arguments: 
-h, --help      show this help message and exit 
--verbose       increase output verbosity
           

說明:

  • 這個選項現在不止是一個需要指派的flag. 我們甚至給TA改了個名字. 我們還新指定了一個關鍵字,

    action

    . 同時吧TA指派成

    "store_true"

    . 這麼做的意思是, 如果使用

    verbose

    , 就把

    True

    指派給

    args.verbose

    . 如果不使用, 就給TA賦

    False

    .
  • 注意help text也發生了變化.

Short options

如果你經常用terminal指令行模式, 你就會發現我還沒說short options. 實作起來其實非常簡單.

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose', help='increase output verbosity',
                     action='store_true')
args = parser.parse_args()
if args.verbose:
    print 'verbosity turned on'
           

輸出:

$ python prog.py -v
verbosity turned on
$ python prog.py --help
usage: prog.py [-h] [-v]

optional arguments:
-h, --help   show this help message and exit 
-v, --verbose   increase output verbosity
           

可以看到在help text裡有對應的改變.

混用positional和optional arguments

讓代碼來的更複雜點吧:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('square', type=int,
        help='display a square of a given number')
parser.add_argument('-v', '--verbose', action='store_true',
        help='increase output verbosity')
args  = parser.parse_args()
answer = args.square ** 2
if args.verbose:
    print 'the square of {} equals {}'.format(args.square, answer)
else:
    print answer
           

輸出:

$ python prog.py
usage: prog.py [-h] [-v] square
prog.py: error: the following arguments are required: square
$ python prog.py 4
16
$ python prog.py 4 --verbose
the square of 4 equals 16
$ python prog.py --verbose 4
the square of 4 equals 16
           
  • 我們又把那個positional argument帶回來了
  • 注意, 指派的順序并沒影響

我們再把以前的verbosity也帶回來:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int, help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int, help="increase output verbosity")
args = parser.parse_args()
answer = args.square ** 2
if args.verbosity == 2: 
        print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity == 1: 
        print "{}^2 == {}".format(args.square, answer)
else: 
        print answer
           

輸出:

$ python prog.py 4
16
$ python prog.py 4 -v
usage: prog.py [-h] [-v VERBOSITY] square
prog.py: error: argument -v/--verbosity: expected one argument
$ python prog.py 4 -v 1
4^2 == 16
$ python prog.py 4 -v 2
the square of 4 equals 16
$ python prog.py 4 -v 3
16
           

看起來都工作的挺好, 除了, 最後好像是有點bug. 我們來通過限定

--verbosity

來fix它:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int, 
                    help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2], help="increase output verbosity")
args = parser.parse_args()
answer = args.square ** 2
if args.verbosity == 2: 
      print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity == 1:
     print "{}^2 == {}".format(args.square, answer)
else: 
     print answer
           

輸出:

$ python prog.py 4 -v 3
usage: prog.py [-h] [-v {0,1,2}] square
prog.py: error: argument -v/--verbosity: invalid choice: 3 (choose from 0, 1, 2)
$ python prog.py 4 -h
usage: prog.py [-h] [-v {0,1,2}] square

positional arguments: 
    square           display a square of a given number
optional arguments: 
    -h, --help      show this help message and exit 
    -v {0,1,2}, --verbosity {0,1,2}
                           increase output verbosity
           

可以看到在error message裡也反應出我們的改變.

接下來, 我們來看下verbosity的另一種玩法, 這種玩法其實更常見, 更符合cpython使用參數的風格(試試python --verison):

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int, 
        help="display the square of a given number")
parser.add_argument("-v", "--verbosity", action="count", 
        help="increase output verbosity")
args = parser.parse_args()
answer = args.square ** 2
if args.verbosity == 2:
       print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity == 1:
       print "{}^2 == {}".format(args.square, answer)
else:
       print answer
           

這回我們用了另一個action: "count". 去統計一個optional argument的出現次數.

$ python prog.py 4
16
$ python prog.py 4 -v
4^2 == 16
$ python prog.py 4 -vv
the square of 4 equals 16
$ python prog.py 4 --verbosity --verbosity
the square of 4 equals 16
$ python prog.py 4 -v 1
usage: prog.py [-h] [-v] square
prog.py: error: unrecognized arguments: 1
$ python prog.py 4 -h
usage: prog.py [-h] [-v] square

positional arguments:
     square     display a square of a given number

optional arguments: 
  -h, --help     show this help message and exit
  -v, --verbosity   increase output verbosity
$ python prog.py 4 -vvv
16
           
  • 跟前面的

    "store_true"

    一樣, 如果不使用, 就會預設指派為

    "None"

    .
  • 這就是

    action

    "count"

    的效果. 你們肯定也在其他程式中見過.
  • 最後的輸出還是看起來怪怪的.

我們來fix一下:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
       help="display a square of a given number")
parser.add_argument("-v", "--verbosity", action="count",
       help="increase output verbosity")
args = parser.parse_args()
answer = args.square ** 2

# bugfix: replace == with >=
if args.verbosity >= 2:
       print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity >= 1:
       print "{}^2 == {}".format(args.square, answer)
else:
       print answer
           

來看看結果:

$ python prog.py 4 -vvv
the square of 4 equals 16
$ python prog.py 4 -vvvv
the square of 4 equals 16
$ python prog.py 4
Traceback (most recent call last): 
      File "prog.py", line 11, in <module>
             if args.verbosity >= 2:
TypeError: unorderable types: NoneType() >= int()
           
  • 從前兩個輸出看起來工作的不錯, fix了我們的bug.
  • 但從最後一個輸出看工作的不怎麼理想啊...

繼續fix:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
       help="display a square of a given number")
parser.add_argument("-v", "--verbosity",
       action="count", default=0, help="increase output verbosity")
args = parser.parse_args()
answer = args.square ** 2
if args.verbosity >= 2:
       print "the square of {} equals {}".format(args.square, answer)
elif args.verbosity >= 1:
       print "{}^2 == {}".format(args.square, answer)
else:
       print answer
           

我們這裡介紹了另一個keyword,

default

. 用了

default

就會把預設值設定成0. 一定要記住如果不給positional argument指派, 預設的就會指派為

None

. 是不能跟數字做比較的.

$ python prog.py 4
16
           

目前介紹的功能已經能應付很多情況了. 在結束之前, 我們再來點更猛的吧.

更進階的用法

我們擴充一下這個例子, 來顯示更多内容:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
parser.add_argument("-v", "--verbosity", action="count", default=0)
args = parser.parse_args()
answer = args.x ** args.y
if args.verbosity >= 2:
     print "Running '{}'".format(__file__)
if args.verbosity >= 1:
     print "{}^{} == {}".format(args.x, args.y, answer)
print answer
           

輸出:

$ python prog.py
usage: prog.py [-h] [-v] x y
prog.py: error: the following arguments are required: x, y
$ python prog.py -h
usage: prog.py [-h] [-v] x y

positional arguments:
     x     the base 
     y     the exponent

optional arguments:
     -h, --help   show this help message and exit
     -v, --verbosity
$ python prog.py 4 2 -v
4^2 == 16
$ python prog.py 4 2 -v
4^2 == 16
$ python prog.py 4 2 -vv
Running 'prog.py'
4^2 == 16
           

處理沖突

我們在例子中加一個argument:

--quiet

.

quiet

表示如果不想用

verbose

的顯示方式就用

quiet

. 它們是互斥的關系. 我們可以這麼實作:

import argparse
parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
args = parser.parse_args()
answer = args.x ** args.y

if args.quiet:
       print answer
elif args.verbose:
       print "{} to the power {} equals {}".format(args.x, args.y, answer)
else:
       print "{}^{} == {}".format(args.x, args.y, answer)
           

輸出:

$ python prog.py 4 2
4^2 == 16
$ python prog.py 4 2 -q
16
$ python prog.py 4 2 -v
4 to the power 2 equals 16
$ python prog.py 4 2 -vq
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
$ python prog.py 4 2 -v --quiet
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
           

最後, 如果你想告訴使用者程式的主要目的. 可以這麼來:

import argparse
parser = argparse.ArgumentParser(description="calculate X to the power of Y")
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
args = parser.parse_args()
answer = args.x ** args.y
if args.quiet:
       print answer
elif args.verbose:
       print "{} to the power {} equals {}".format(args.x, args.y, answer)
else:
       print "{}^{} == {}".format(args.x, args.y, answer)
           

輸出:

$ python prog.py --help
usage: prog.py [-h] [-v | -q] x y

calculate X to the power of Y

positional arguments:
    x     the base 
    y     the exponent

optional arguments:
    -h, --help     show this help message and exit
    -v, --verbose
    -q, --quiet
           

作者:Edward_f0cus

連結:https://www.jianshu.com/p/a50aead61319

來源:簡書

簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。