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('$$'

我有两个类似的代码需要解析,我不确定用哪种最适合Python的方式来完成这一任务

假设我有两个相似的“代码”

这两个代码都以
$$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

散列以类似的方式工作,因为一个带有somenamesomevalue的变量,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
函数使它更清晰


我希望这会有所帮助

我不确定您使用的是什么约束,但它看起来像:

  • 有不同类型的代码和不同的规则
  • 破折号分隔参数的数量可能会有所不同
  • 哪个arg具有管道可能会有所不同
  • 简单的示例

    这不太难解决,而且您不需要花哨的包装,所以我会放弃它们,因为它增加了阅读的复杂性

    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)
    

    我的建议如下:

    • 不够详细
    • 明确区分一般逻辑和具体逻辑
    • 具有足够的可扩展性
    基本上,它将公共逻辑和特定逻辑划分为不同的函数(您可以使用OOP执行相同的操作)。问题是,它使用一个包含逻辑的映射器变量,根据每个代码的内容选择特定的解析器。下面是:

        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个区别:

    • 值的数目
    • 解析“内部”值的位置
    • 要采用的“内部”值的位置
    我们可以编写parse func