Python 如何组合两个外部函数向内部函数提供参数的函数
我有两个类似的代码需要解析,我不确定用哪种最适合Python的方式来完成这一任务 假设我有两个相似的“代码” 这两个代码都以Python 如何组合两个外部函数向内部函数提供参数的函数,python,functional-programming,Python,Functional Programming,我有两个类似的代码需要解析,我不确定用哪种最适合Python的方式来完成这一任务 假设我有两个相似的“代码” 这两个代码都以$$otherthing结尾,并包含由- 起初,我想到使用functools.wrap将一些常见逻辑与每种类型代码的特定逻辑分开,如下所示: from functools import wraps def parse_secret(f): @wraps(f) def wrapper(code, *args): _code = code.split('$$'
$$otherthing
结尾,并包含由-
起初,我想到使用functools.wrap
将一些常见逻辑与每种类型代码的特定逻辑分开,如下所示:
from functools import wraps
def parse_secret(f):
@wraps(f)
def wrapper(code, *args):
_code = code.split('$$')[0]
return f(code, *_code.split('-'))
return wrapper
@parse_secret
def parse_code_1b(code, a, b, c):
a = a.split('|')[0]
return (a,b,c)
@parse_secret
def parse_code_2b(code, a, b):
b = b.split('|')[1]
return (a,b)
def _parse_secret(parse_func, code):
_code = code.split('$$')[0]
return parse_func(code, *_code.split('-'))
def _parse_code_1(code, a, b, c):
"""
a, b, and c are descriptive parameters that explain
the different components in the secret code
returns a tuple of the decoded parts
"""
a = a.split('|')[0]
return (a,b,c)
def _parse_code_2(code, a, b):
"""
a and b are descriptive parameters that explain
the different components in the secret code
returns a tuple of the decoded parts
"""
b = b.split('|')[1]
return (a,b)
def parse_code_1(code):
return _parse_secret(_parse_code_1, code)
def parse_code_2(code):
return _parse_secret(_parse_code_2, code)
然而,这样做会让人有点困惑,究竟应该传递给parse\u code.*
函数的参数是什么
parse_code_1b(secret_code_1)
parse_code_2b(secret_code_2)
因此,为了使函数的形式参数更易于推理,我将逻辑更改为如下内容:
from functools import wraps
def parse_secret(f):
@wraps(f)
def wrapper(code, *args):
_code = code.split('$$')[0]
return f(code, *_code.split('-'))
return wrapper
@parse_secret
def parse_code_1b(code, a, b, c):
a = a.split('|')[0]
return (a,b,c)
@parse_secret
def parse_code_2b(code, a, b):
b = b.split('|')[1]
return (a,b)
def _parse_secret(parse_func, code):
_code = code.split('$$')[0]
return parse_func(code, *_code.split('-'))
def _parse_code_1(code, a, b, c):
"""
a, b, and c are descriptive parameters that explain
the different components in the secret code
returns a tuple of the decoded parts
"""
a = a.split('|')[0]
return (a,b,c)
def _parse_code_2(code, a, b):
"""
a and b are descriptive parameters that explain
the different components in the secret code
returns a tuple of the decoded parts
"""
b = b.split('|')[1]
return (a,b)
def parse_code_1(code):
return _parse_secret(_parse_code_1, code)
def parse_code_2(code):
return _parse_secret(_parse_code_2, code)
现在更容易对传递给函数的内容进行推理:
parse_code_1(secret_code_1)
parse_code_2(secret_code_2)
secret_code_1 = 'asdf|qwer-sdfg-wert$$otherthing'
secret_code_2 = 'qwersdfg-qw|er$$otherthing'
results = [parse_code_1(secret_code_1), parse_code_2(secret_code_2)]
print(results)
但是,这段代码要详细得多
有更好的方法吗?使用类的面向对象方法在这里更有意义吗
我认为您需要提供更多信息,确切说明您正试图实现的目标,以及明确的限制条件。例如,
$$
可以发生多少次?是否总是有一个|
dividor?那种事
要广泛地回答您的问题,一种优雅的python方法是使用python的解包特性,并结合split。比如说
secret_code_1 = 'asdf|qwer-sdfg-wert$$otherthing'
first_$$_part, last_$$_part = secret_code_1.split('$$')
通过使用此技术,除了简单的
if
块之外,您还应该能够编写一个优雅的解析器。我相信类似的方法可以奏效:
secret_codes = ['asdf|qwer-sdfg-wert$$otherthing', 'qwersdfg-qw|er$$otherthing']
def parse_code(code):
_code = code.split('$$')
if '-' in _code[0]:
return _parse_secrets(_code[1], *_code[0].split('-'))
return _parse_secrets(_code[0], *_code[1].split('-'))
def _parse_secrets(code, a, b, c=None):
"""
a, b, and c are descriptive parameters that explain
the different components in the secret code
returns a tuple of the decoded parts
"""
if c is not None:
return a.split('|')[0], b, c
return a, b.split('|')[1]
for secret_code in secret_codes:
print(parse_code(secret_code))
输出:
('asdf', 'sdfg', 'wert')
('qwersdfg', 'er')
我不确定你的秘密数据结构,但如果你使用元素位置的索引,其中包含|的数据,并且有适当数量的秘密数据,你也可以这样做,并且可能有无限(几乎)数量的秘密:
def _parse_secrets(code, *data):
"""
data is descriptive parameters that explain
the different components in the secret code
returns a tuple of the decoded parts
"""
i = 0
decoded_secrets = []
for secret in data:
if '|' in secret:
decoded_secrets.append(secret.split('|')[i])
else:
decoded_secrets.append(secret)
i += 1
return tuple(decoded_secrets)
我真的不知道你到底是什么意思。但我有一个想法,这可能就是你们要找的
使用这样一个简单的函数怎么样:
from functools import wraps
def parse_secret(f):
@wraps(f)
def wrapper(code, *args):
_code = code.split('$$')[0]
return f(code, *_code.split('-'))
return wrapper
@parse_secret
def parse_code_1b(code, a, b, c):
a = a.split('|')[0]
return (a,b,c)
@parse_secret
def parse_code_2b(code, a, b):
b = b.split('|')[1]
return (a,b)
def _parse_secret(parse_func, code):
_code = code.split('$$')[0]
return parse_func(code, *_code.split('-'))
def _parse_code_1(code, a, b, c):
"""
a, b, and c are descriptive parameters that explain
the different components in the secret code
returns a tuple of the decoded parts
"""
a = a.split('|')[0]
return (a,b,c)
def _parse_code_2(code, a, b):
"""
a and b are descriptive parameters that explain
the different components in the secret code
returns a tuple of the decoded parts
"""
b = b.split('|')[1]
return (a,b)
def parse_code_1(code):
return _parse_secret(_parse_code_1, code)
def parse_code_2(code):
return _parse_secret(_parse_code_2, code)
def split_secret_代码(代码):
返回[code]+code[:code.find($$)。拆分(“-”)
而不仅仅是使用:
parse_code_1(*split_secret_code(secret_code_1))
如果我理解正确,您希望能够像传递解析参数一样定义函数,但希望将未解析的代码传递给函数
您可以这样做,非常类似于您提出的第一个解决方案
from functools import wraps
def parse_secret(f):
@wraps(f)
def wrapper(code):
args = code.split('$$')[0].split('-')
return f(*args)
return wrapper
@parse_secret
def parse_code_1(a, b, c):
a = a.split('|')[0]
return (a,b,c)
@parse_secret
def parse_code_2(a, b):
b = b.split('|')[1]
return (a,b)
对于示例中提到的密码
secret_code_1 = 'asdf|qwer-sdfg-wert$$otherthing'
print (parse_code_1(secret_code_1))
>> ('asdf', 'sdfg', 'wert')
secret_code_2 = 'qwersdfg-qw|er$$otherthing'
print (parse_code_2(secret_code_2))
>> ('qwersdfg', 'er')
我不理解你的问题,也不理解你的代码,但也许一个简单的方法是通过正则表达式
import re
secret_code_1 = 'asdf|qwer-sdfg-wert$$otherthing'
secret_code_2 = 'qwersdfg-qw|er$$otherthing'
def parse_code(code):
regex = re.search('([\w-]+)\|([\w-]+)\$\$([\w]+)', code) # regular expression
return regex.group(3), regex.group(1).split("-"), regex.group(2).split("-")
otherthing, first_group, second_group = parse_code(secret_code_2)
print(otherthing) # otherthing, string
print(first_group) # first group, list
print(second_group) # second group, list
输出:
otherthing
['qwersdfg', 'qw']
['er']
你嫁给了字符串解析吗?如果您正在传递带有值的变量,并且不需要变量名,则可以将它们“打包”为整数 如果您使用的是密码学,您可以制定一个长的十六进制字符数,然后将其作为int和“stop”字节传递(例如,0000,因为“0”实际上是48 try:
chr(48)
),如果您与字符串结合,我建议使用一个较低的字符字节标识符,例如(1->aka try:chr(1)
)因此,您可以扫描整数并将其移位8位,以获得具有8位掩码的字节(这看起来像(secret\u code>>8)&0xf
散列以类似的方式工作,因为一个带有somename和somevalue的变量,somename和somevalue可以解析为整数,然后与stop模块连接,然后在需要时检索
让我给你举个散列的例子
# lets say
a = 1
# of sort hashing would be
hash = ord('a')+(0b00<<8)+(1<<16)
#where a hashed would be 65633 in integer value on 64 bit computer
# and then you just need to find a 0b00 aka separator
然后,您可以将其映射为:
mapProcces([str.lower,str.upper,str.title],"stackowerflow")
或者,您可以简单地用空格替换每个限定分隔符,然后拆分空格
secret_code_1 = 'asdf|qwer-sdfg-wert$$otherthing'
separ = "|,-,$".split(",")
secret_code_1 = [x if x not in separ else " " for x in secret_code_1]# replaces separators with empty chars
secret_code_1 = "".join(secret_code_1) #coverts list to a string
secret_code_1 = secret_code_1.split(" ") #it splited them to list
secret_code_1 = filter(None,secret_code_1) # filter empty chars ''
first,second,third,fourth,other = secret_code_1
这样,你的秘密代码被拆分并分配给确定数量的变量。当然,你可以使用“”作为声明,你可以使用任何你想要的,你可以用“someseparator”替换每个分隔符,然后用“someseparator”拆分。你也可以使用str.replace
函数使它更清晰
我希望这会有所帮助我不确定您使用的是什么约束,但它看起来像:
def pre_parse(code):
dash_code, otherthing = code.split('$$')
return dash_code.split('-')
def parse_type_1(code):
dash_args = pre_parse(code)
dash_args[0], toss = dash_args[0].split('|')
return dash_args
def parse_type_2(code):
dash_args = pre_parse(code)
toss, dash_args[1] = dash_args[1].split('|')
return dash_args
# Example call
parse_type_1(secret_code_1)
试图回答所述问题
您可以通过使用python的本机decorator模式结合*
,以这种方式提供参数,它将位置参数滚动/展开到一个元组中,因此您不需要确切知道有多少个
def dash_args(code):
dash_code, otherthing = code.split('$$')
return dash_code.split('-')
def pre_parse(f):
def wrapper(code):
# HERE is where the outer function, the wrapper,
# supplies arguments to the inner function.
return f(code, *dash_args(code))
return wrapper
@pre_parse
def parse_type_1(code, *args):
new_args = list(args)
new_args[0], toss = args[0].split('|')
return new_args
@pre_parse
def parse_type_2(code, *args):
new_args = list(args)
toss, new_args[1] = args[1].split('|')
return new_args
# Example call:
parse_type_1(secret_code_1)
更多可扩展示例
如果出于某种原因需要支持这种解析的许多变体,可以使用简单的OOP设置,如
class BaseParser(object):
def get_dash_args(self, code):
dash_code, otherthing = code.split('$$')
return dash_code.split('-')
class PipeParser(BaseParser):
def __init__(self, arg_index, split_index):
self.arg_index = arg_index
self.split_index = split_index
def parse(self, code):
args = self.get_dash_args(code)
pipe_arg = args[self.arg_index]
args[self.arg_index] = pipe_arg.split('|')[self.split_index]
return args
# Example call
pipe_parser_1 = PipeParser(0, 0)
pipe_parser_1.parse(secret_code_1)
pipe_parser_2 = PipeParser(1, 1)
pipe_parser_2.parse(secret_code_2)
我的建议如下:
- 不够详细
- 明确区分一般逻辑和具体逻辑
- 具有足够的可扩展性
def parse_common(code):
"""
Provides common parsing logic.
"""
encoded_components = code.split('$$')[0].split('-')
return encoded_components
def parse_code_1(code, components):
"""
Specific parsing for type-1 codes.
"""
components[0] = components[0].split('|')[0] # decoding some type-1 component
return tuple([c for c in components])
def parse_code_2(code, components):
"""
Specific parsing for type-2 codes.
"""
components[1] = components[1].split('|')[1] # decoding some type-2 component
return tuple([c for c in components])
def parse_code_3(code, components):
"""
Specific parsing for type-3 codes.
"""
components[2] = components[2].split('||')[0] # decoding some type-3 component
return tuple([c for c in components])
# ... and so on, if more codes need to be added ...
# Maps specific parser, according to the number of components
CODE_PARSER_SELECTOR = [
(3, parse_code_1),
(2, parse_code_2),
(4, parse_code_3)
]
def parse_code(code):
# executes common parsing
components = parse_common(code)
# selects specific parser
parser_info = [s for s in CODE_PARSER_SELECTOR if len(components) == s[0]]
if parser_info is not None and len(parser_info) > 0:
parse_func = parser_info[0][1]
return parse_func(code, components)
else:
raise RuntimeError('No parser found for code: %s' % code)
secret_codes = [
'asdf|qwer-sdfg-wert$$otherthing', # type 1
'qwersdfg-qw|er$$otherthing', # type 2
'qwersdfg-hjkl-yui||poiuy-rtyu$$otherthing' # type 3
]
print [parse_code(c) for c in secret_codes]
功能性方法更简洁,更有意义
我们可以从表达概念开始,以最容易组合的形式
compose = lambda length, p, q: \
lambda code: parse_code(parse_secret(code)[:length], p, q)
parse_code_1 = compose(3, 0, 0)
parse_code_2 = compose(2, 1, 1)
剥离$$otherthing
并拆分值:
parse_secret = lambda code: code.split('$$')[0].split('-')
取一个内部值:
take = lambda value, index: value.split('|')[index]
将其中一个值替换为其内部值:
parse_code = lambda values, p, q: \
[take(v, q) if p == i else v for (i, v) in enumerate(values)]
这两种类型的代码有3个区别:
- 值的数目
- 解析“内部”值的位置
- 要采用的“内部”值的位置