2016-01-19 79 views
0

我正在使用Python,並且編寫了自己的腳本,允許我檢查程序運行時提供的參數。下面的我想要實現的一個例子:將代碼存儲在字典中

python file.py -v -h anotherfile.py

./file.py -v -h anotherfile.py

在這兩種情況下,-v-h參數,打印出的模塊版本,和基本的幫助文件。我已經有了區分參數和文件的代碼,除了我想在這個問題上創建一個通用模塊。

寫在Java的

// Somewhere. 
public static HashMap<String, Runnable> args = new HashMap<String, Runnable>(); 
public void addArgument(String argument, Runnable command) { 
    if (argument.length() > 0) { 
     if (args.get(argument) == null) { 
      args.put(argument, command); 
     } else { 
      System.err.println("Cannot add argument: " + argument + " to HashMap as the mapping already exists."); 
      // Recover. 
     } 
    } 
} 

// Somewhere else. 
foo.addArgument("-v",() -> {System.out.println("version 1.0");}); 
foo.args.get("-v").run(); 

下面的代碼 - 將會運行Lambda表達式(ATLEAST這是我閱讀研究的話題時,他們)成功。我不知道Lambda表達式是如何工作的,並且只具有使用它們的基本知識。

這個問題的關鍵是,我如何在Python中實現類似Java示例的東西,將任何類型的代碼存儲在數組中?

的事情是與Java例子不過,如果我有在執行addArgument並使用i莫名其妙或更確切地說,包含類addArgument知道使用i從調用它的一個類中定義int i = 0;。我擔心這可能不是Python的情況...

我希望能夠將它們存儲在字典或其他類型的基於鍵的數組中,所以我可以將它們存儲在以下方式:

# Very rough example on the latter argument, showing what I'm after. 
addoption("-v", print("version 1.0")) 

編輯:什麼,我想舉例:(不工作的是)(請忽略;公司)

args = {}; 

def add(argument, command): 
    args[argument] = lambda: command; # Same problem when removing 'lambda:' 

def run(): 
    for arg in args: 
     arg(); # Causing problems. 

def prnt(): 
    print("test"); 

add("-v", prnt); 
run(); 

回答

1

編輯:糾正你最近的代碼,遍歷字典生成它的鍵而不是它的價值,所以你需要:

args = {}; 

def add(argument, command): 
    args[argument] = command; 

def run(): 
    for arg in args: 
     args[arg]()  # <<<<<<<<<< 

def prnt(): 
    print("test"); 

add("-v", prnt); 
run(); 

對於你給的例子,功能的字典,雖然有可能,不是嗎在Python中處理事情真的很自然。標準庫有一個模塊,argparse專門用於處理與命令行參數相關的所有內容,而不是使用字典中的鍵來解析命令行參數並引用其存儲的常量。

import argparse 

def output_version(): 
    print('Version 1.0!') 

parser = argparse.ArgumentParser(description="A program to do something.") 
parser.add_argument('-v', help='Output version number.', action='store_true') 

args = parser.parse_args() 
if args.v: 
    output_version() 

(實際上輸出一個版本字符串也原生​​處理:參見here)。

打印出的文本文件的內容,當-p開關給出myfile.txt

import argparse 

def print_file(filename): 
    with open(filename) as fi: 
     print(fi.read()) 

parser = argparse.ArgumentParser(description="A program to do something.") 
parser.add_argument('-p', help='Print a plain file.', action='store') 

args = parser.parse_args() 

if args.p: 
    print_file(args.p) 

使用帶有例如

$ prog.py -p the_filename.txt 
+0

我如何將純文件的內容打印爲參數的動作? – finnrayment

+0

你可以定義一個函數來做到這一點,然後當參數解析器包含相應的開關時調用它。你是否也想在命令行上指定文件名? – xnx

+0

當然。我創建了一個通用模塊,我可以在其中**指定**任何和所有**參數**和文件**的任何**動作。 – finnrayment

0

在Python中,你可以簡單地使用參考作爲數據結構中的值的函數。例如,考慮下面的代碼:

def spam(): 
    print('Ham!') 

eggs = [spam, spam, spam] 
for x in eggs: 
    x() 

這將調用該函數spam的三個實例。

您所指的lambda expressions只是定義函數的另一種方式,不需要將它們綁定到名稱。考慮以下幾點:

eggs = [lambda : print('ham'), lambda : print('spam')] 
for x in eggs: 
    x() 

這得到更加強大,當你使用的參數,但:

fn = [lambda x: return x + 3, lambda x: return x * 2] 
for f in fn: 
    print(f(4)) 

一旦你有一個函數的引用,然後可以通過另一功能。

def foo(x): 
    return x + 2 

bar = lambda x: return x * 2 

def h(g, f, x): 
    return g(f(x)) 

print(h(foo, bar, 37)) 

但是,在您的方案中,您可以簡單地通過lambda : print("version 1.0")

+0

第一個例子!有沒有一種方法可以將'spam()'作爲「def」的參數? – finnrayment

+0

類似於'def foo(boo):boo()' – finnrayment

+0

當然(假設我理解正確)。我會更新我的答案。編輯:是的,正是如此。 – Joost

-1

Python有一個叫做eval()的函數,它接收字符串並嘗試將它們評估爲代碼。

>>> eval("2+3") 
5 

然後你可以使用3個引號

x = """the quick brown fox 
jumps over the 
lazy dogs""" 

你的代碼存儲爲多行字符串如果你想存儲函數本身,沒有任何原因,他們不能也被放置在一個字典。即使沒有lambda表達式。

def f(): 
    return 1 

def g(x): 
    return x + 1 

def h(x): 
    return 2*x 

F = [f,g,h] 
G = {"a": f, "b": g, "c": h} 

(F[0](), G["a"]()) 

該元組的值是(1,1)。否則我不知道你在問什麼。

+0

是的。這絕對有效!除了我想要原始代碼存儲... – finnrayment

+0

@frayment Python並沒有真正做到這一點。您可以存儲*函數*,或者可以將*代碼*作爲字符串存儲並對其進行評估。 –

+0

那麼前者就是我想要實現的。 – finnrayment

0

由於在Python函數中是一流的對象,因此您可以創建{string: callable}對的字典。

def help(): 
    print("Usage: xyz") 


d = { 
    'help': help, 
    'version': lambda: print("1.0"), # lambda is also callable 
} 

像使用定義之後將以下內容:

my_function = d["help"] # retrieves function stored under key 'help' in dict 
my_function() # calls function 

# or obviously you may drop explainatory variable 
d['help']() 

它會與你的問題的定製解決方案這樣的定義的工作。

對於創建命令行界面的標準化方式,您可能需要熟悉argparse module

+0

我可以將它修改爲:'addargument(arg,function)',將函數放在不同的模塊中,並用'addargument(「 - v」,argnamegoeshere)'調用它。 – finnrayment