簡體   English   中英

動態地循環遍歷Python中函數的函數列表

[英]Looping through list of functions in a function in Python dynamically

我想看看是否可以在函數中運行函數列表。 我能找到的最接近的東西是循環整個模塊。 我只想使用預先選擇的功能列表。

這是我原來的問題:

  1. 給定一個字符串,檢查每個字母以查看是否滿足5個測試中的任何一個。
  2. 如果至少1個字母通過檢查,則返回True。
  3. 如果字符串中的所有字母都未通過檢查,則返回False。
  4. 對於字符串中的每個字母,我們將檢查這些函數:isalnum(),isalpha(),isdigit(),islower(),isupper()
  5. 每個測試的結果應該打印到不同的行。

樣本輸入

    qA2

樣本輸出(必須打印到單獨的行,如果至少一個字母通過則為True,否則為每個測試的所有字母都失敗):

    True
    True
    True
    True
    True

我寫了一個測試。 當然我可以寫出5組不同的代碼,但這看起來很難看。 然后我開始想知道我是否可以循環完成他們要求的所有測試。

僅一個測試的代碼:

    raw = 'asdfaa3fa'
    counter = 0
    for i in xrange(len(raw)):
        if raw[i].isdigit() == True: ## This line is where I'd loop in diff func's
            counter = 1
            print True
            break
    if counter == 0:
        print False

我嘗試使用所有測試運行循環失敗:

    raw = 'asdfaa3fa'
    lst = [raw[i].isalnum(),raw[i].isalpha(),raw[i].isdigit(),raw[i].islower(),raw[i].isupper()]
    counter = 0
    for f in range(0,5):
        for i in xrange(len(raw)):
            if lst[f] == True: ## loop through f, which then loops through i
                print lst[f] 
                counter = 1
                print True
        break
        if counter == 0:
    print False

那么如何修復此代碼以實現所有規則呢?


使用來自所有注釋的信息 - 此代碼滿足上述規則,同時動態循環遍歷每個方法。

    raw = 'ABC'
    functions = [str.isalnum, str.isalpha, str.isdigit, str.islower,  str.isupper]

    for func in functions:
        print any(func(letter) for letter in raw)

getattr方法(我認為這被稱為內省方法?)

    raw = 'ABC'

    meths = ['isalnum', 'isalpha', 'isdigit', 'islower', 'isupper']
    for m in meths: 
        print any(getattr(c,m)() for c in raw)

列表理解方法:

    from __future__ import print_function ## Changing to Python 3 to use print in list comp

    raw = 'ABC'
    functions = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
    solution = [print(func(raw)) for func in functions]

循環瀏覽函數列表的方式略有不同。 這將是一種有效的方法。 您需要存儲在列表中的函數是str.funcname給出的通用字符串函數。 一旦你有了這些函數列表,就可以使用for循環遍歷它們,並將其視為普通函數!

raw = 'asdfaa3fa'
functions = [str.isalnum, str.isalpha, str.isdigit, str.islower,  str.isupper]  # list of functions

for fn in functions:     # iterate over list of functions, where the current function in the list is referred to as fn
    for ch in raw:       # for each character in the string raw
        if fn(ch):        
            print(True)
            break

樣本輸出:

Input                     Output
===================================
"qA2"         ----->      True True True True True
"asdfaa3fa"   ----->      True True True True

另外我注意到你似乎使用索引進行迭代,這讓我覺得你可能會來自像C / C ++這樣的語言。 for循環結構在python中非常強大,所以我會讀它(y)。

上面是一個更加pythonic的方式來做到這一點,但作為一個學習工具,我寫了一個工作版本,與你試圖盡可能多地做到這一點,以顯示你特別錯誤的地方。 這是評論:

raw = 'asdfaa3fa'
lst = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]   # notice youre treating the functions just like variables and aren't actually calling them. That is, you're writing str.isalpha instead of str.isalpha()
for f in range(0,5):
    counter = 0
    for i in xrange(len(raw)):
        if lst[f](raw[i]) == True:  # In your attempt, you were checking if lst[f]==True; lst[f] is a function so you are checking if a function == True. Instead, you need to pass an argument to lst[f](), in this case the ith character of raw, and check whether what that function evaluates to is true
            print lst[f] 
            counter = 1
            print True
            break
    if counter == 0:
        print False

好的,所以第一個問題很簡單。 這樣做的簡單方法就是這樣做

def foo(raw):
  for c in raw:
    if c.isalpha(): return True
    if c.isdigit(): return True
    # the other cases
  return False

永遠不要忽視可行的最簡單的事情。

現在,如果你想動態地做 - 這是你可能需要的魔術關鍵詞,你想要應用這樣的東西(從另一個問題中抄襲):

meths = [isalnum, isalpha, isdigit, islower, isupper]
for c in raw:    
  for m in meths:
    getattr(c, m)()

警告,這是未經測試的代碼,旨在為您提供這個想法。 這里的關鍵概念是對象的方法就像其他任何東西一樣屬性,因此,例如getattr("a", "isalpha")()執行以下操作:

  • 使用getattr在名為isalpha的方法中搜索"a"的屬性字典
  • 返回該方法本身 - <function isalpha>
  • 然后使用()這是Python中的函數應用程序運算符來調用該方法。

看這個例子:

In [11]: getattr('a', 'isalpha')()
Out[11]: True

回答原來的問題:

raw = 'asdfa3fa'
functions = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
isanything = [func(raw) for func in functions]
print repr(isanything)

所有其他答案都是正確的,但由於您是初學者,我想在您的代碼中指出問題:

lst = [raw[i].isalnum(),raw[i].isalpha(),raw[i].isdigit(),raw[i].islower(),raw[i].isupper()]

第一:不確定的代碼中當前有哪個值被剪切,但它似乎指向字符串中的某個位置 - 這導致單個字符被評估,而不是整個字符串raw

第二:當你構建你的列表時,你已經調用了你要插入的方法,這個方法不是自己插入函數,而是它們的返回值(這就是為什么你在print語句中看到所有那些True值的原因) )。

嘗試更改代碼,如下所示:

lst = [raw.isalnum, raw.isalpha, raw.isdigit, raw.islower, raw.isupper]

我猜你要驗證密碼的復雜性,而且我也會說那個接受輸入並說“False”的軟件而且沒有任何跡象表明為什么用戶是敵對的,所以最重要的不是“如何循環嵌套的char函數代碼wizardry(*)”但“給出了很好的反饋”,並建議更像:

raw = 'asdfaa3fa'

import re

def validate_password(password):
    """ This function takes a password string, and validates it
        against the complexity requirements from {wherever}
        and returns True if it's complex enough, otherwise False """

    if not re.search('\d', password):
        print("Error: password needs to include at least one number")
        return False

    elif not re.search('[a-z]', password):
        print("Error: password must include at least one lowercase letter")
        return False

    elif not re.search('[A-Z]', password):
        print("Error: password must include at least one uppercase letter")
        return False

    print("Password is OK")
    return True

validate_password(raw)

在repl.it上在線試用

正則表達式搜索在一次調用中檢查字符和數字的范圍,這比字符循環更整潔。

(PS。你的函數重疊;一個字符串,其字符匹配'isupper','islower'和'isnumeric'已經有'isadigit'和'isalnum'覆蓋。更有趣的是處理像!這些不是上層,下層的字符,數字或alnum)。


(*)像其他答案一樣的功能魔法通常就是我要回答的內容,但是有很多已經回答的內容,我可能會回答其他方式:P

由於您循環遍歷簡單項的列表並嘗試查找是否all函數都有any有效結果,因此您只需定義要在輸入上調用的函數列表並返回該函數。 這是你想要實現的一個相當pythonic的例子:

def checker(checks, value):
    return all(any(check(r) for r in value) for check in checks)

測試出來:

>>> def checker(checks, value):
...     return all(any(check(r) for r in value) for check in checks)
... 
>>> checks = [str.isalnum, str.isalpha, str.isdigit, str.islower, str.isupper]
>>> checker(checks, 'abcdef123ABC')
True
>>> checker(checks, 'abcdef123')
False
>>> 

您可以使用內省循環遍歷所有對象的屬性,無論它們是函數還是其他類型。

但是你可能不想在這里這樣做,因為str很多函數屬性,而你只對它們中的五個感興趣。 這可能比你做的更好,只需列出你想要的五個。

另外,如果你不想,你不需要遍歷字符串的每個字符; 那些函數已經查看了整個字符串。

查看這個針對您的問題的單行解決方案。 那個問題來自HackerRank。 我使用內置的getattr函數遍歷函數列表。

s='qA2'
[print(bool(list(filter(lambda x : getattr(x, func)(),s)))) for func in ['isalnum','isalpha','isdigit','islower','isupper']]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM