[英]Looping through list of functions in a function in Python dynamically
我想看看是否可以在函數中運行函數列表。 我能找到的最接近的東西是循環整個模塊。 我只想使用預先選擇的功能列表。
這是我原來的問題:
樣本輸入
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)
正則表達式搜索在一次調用中檢查字符和數字的范圍,這比字符循環更整潔。
(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.