Python如何优雅地处理不同数据结构的使用?

Python如何优雅地处理不同数据结构的使用?,python,data-structures,Python,Data Structures,我正在使用Python 3.5,这是我目前正在处理的代码: def is_odd_number(n): """states if n is an odd number""" return n % 2 == 1 def collatz_next(n): """returns the successor to n in Collatz sequence""" return 3*n + 1 if is_odd_number(n) else n//2 def co

我正在使用Python 3.5,这是我目前正在处理的代码:

def is_odd_number(n):
    """states if n is an odd number"""
    return n % 2 == 1


def collatz_next(n):
    """returns the successor to n in Collatz sequence"""
    return 3*n + 1 if is_odd_number(n) else n//2


def collatz_seq_sum(seq):
    """returns the sum of all elements to a given Collatz sequence"""
    return sum(seq)


def collatz_seq(n):
    """returns the Collatz sequence to n"""
    l = []
    l.append(n)
    current = n
    while current != 1:
        next_one = collatz_next(current)
        l.append(next_one)
        current = next_one
    return l


def collatz_seqs(lower_limit=1, upper_limit=10):
    """returns Collatz sequences from lower_limit to upper_limit"""
    return {i: collatz_seq(i) for i in range(lower_limit, upper_limit+1)}
我认为类型
list
在处理单个Collatz序列时是最好的。这就是为什么
collatz\u seq
返回一个列表。然而,我发现在处理一行中的多个参数
n
时,观察这个特定序列是如何发展的很有趣。这就是为什么我创建了
collatz\seqs

我不喜欢
collatz\u seq\u sum
,原因很简单:它只有在参数
seq
的类型为
list
时才能正常工作。在我看来,
collatz\u seq\u sum
没有责任确保提供正确的实际参数,在这种情况下,
列表由自然数组成。在我看来,
collatz\u seq\u sum
的调用方必须确保提供了正确的参数

我想要
collatz\u sum\u seq
处理单个和多个序列
collatz_seq
返回一个
列表
collatz_seq
返回一个
dict
。因此,我的问题是:如何确保
collatz\u seq\u sum
始终为其参数
seq
获取正确的数据类型?如果
collatz\u seq\u sum
不关心其参数
seq
的数据类型,如何才能使
collatz\u seq\u sum
正常工作?我的第一个想法是更改
collatz\u seq
,让它返回一个
dict
,而不是
list
,并更改
collatz\u seq\u sum
,以便处理
dict
。但是,我不喜欢这种方法,因为在处理单个序列时,我不希望使用
dict


你有什么解决办法吗?非常感谢您。

如果我理解正确,您希望
collatz\u seq\u sum
同时使用collatz序列或单个collatz序列。对于字典,您希望函数返回单个collatz序列和的字典

您可以使用
isinstance
检查输入的
seq
是字典还是列表,并针对每种情况运行不同的代码。下面的代码可以工作

def collatz_seq_sum(seq):
    """returns the sum of all elements to a given Collatz sequence"""
    if isinstance(seq, dict):
        return {i: sum(seqi) for i, seqi in seq.items()}
    else:
        return sum(seq)
但是,如果您想要的是dict的所有序列的总和,那么您可以使用以下内容

def collatz_seq_sum(seq):
    """returns the sum of all elements to a given Collatz sequence"""
    if isinstance(seq, dict):
        return sum([sum(seqi) for i, seqi in seq.items()])
    else:
        return sum(seq)

如果我理解正确,您希望
collatz_seq_sum
同时处理collatz序列或单个collatz序列。对于字典,您希望函数返回单个collatz序列和的字典

您可以使用
isinstance
检查输入的
seq
是字典还是列表,并针对每种情况运行不同的代码。下面的代码可以工作

def collatz_seq_sum(seq):
    """returns the sum of all elements to a given Collatz sequence"""
    if isinstance(seq, dict):
        return {i: sum(seqi) for i, seqi in seq.items()}
    else:
        return sum(seq)
但是,如果您想要的是dict的所有序列的总和,那么您可以使用以下内容

def collatz_seq_sum(seq):
    """returns the sum of all elements to a given Collatz sequence"""
    if isinstance(seq, dict):
        return sum([sum(seqi) for i, seqi in seq.items()])
    else:
        return sum(seq)

在python中为函数执行多态性的唯一方法是检查给定参数的类型:

from collections.abc import Mapping, Iterable

def collatz_seq_sum(seq):
    """returns the sum of all elements to a given Collatz sequence"""
    if isinstance(seq, Mapping):
        ret = {key: sum(values) for key, values in seq.items()}
    elif isinstance(seq, Iterable):
        ret = sum(seq)
    else:
        msg = "collatz_seq_sum got unexpected type: '{}'".format(type(seq))
        raise TypeError(msg)
    return ret

如果您希望函数根据输入的类型表现出不同的行为,这是一种方法。

在python中为函数执行多态性的唯一方法是检查给定参数的类型:

from collections.abc import Mapping, Iterable

def collatz_seq_sum(seq):
    """returns the sum of all elements to a given Collatz sequence"""
    if isinstance(seq, Mapping):
        ret = {key: sum(values) for key, values in seq.items()}
    elif isinstance(seq, Iterable):
        ret = sum(seq)
    else:
        msg = "collatz_seq_sum got unexpected type: '{}'".format(type(seq))
        raise TypeError(msg)
    return ret
如果您希望函数根据输入的类型表现出不同的行为,这是一种方法。

Python3.4+-允许您根据参数的类型重载函数定义

from functools import singledispatch

@singledispatch
def collatz_seq_sum(seq):
    '''returns the sum of all elements to a given Collatz sequence'''
    raise NotImplementedError("I can't handle that data type")

@collatz_seq_sum.register(list)
def _(seq):
    return sum(seq)

@collatz_seq_sum.register(dict)
def _(seq):
    return {key: sum(values) for key, values in seq.items()}

>>> collatz_seq_sum([1,2,3,4,5])
15
>>> collatz_seq_sum({'a': [1,1,1,1], 'b': [2,2,2,2]})
{'a': 4, 'b': 8}
使用list或dict以外的内容调用
collatz\u seq\u sum
,将引发
NotImplementedError

Python 3.4+-允许您根据参数的类型重载函数定义

from functools import singledispatch

@singledispatch
def collatz_seq_sum(seq):
    '''returns the sum of all elements to a given Collatz sequence'''
    raise NotImplementedError("I can't handle that data type")

@collatz_seq_sum.register(list)
def _(seq):
    return sum(seq)

@collatz_seq_sum.register(dict)
def _(seq):
    return {key: sum(values) for key, values in seq.items()}

>>> collatz_seq_sum([1,2,3,4,5])
15
>>> collatz_seq_sum({'a': [1,1,1,1], 'b': [2,2,2,2]})
{'a': 4, 'b': 8}

使用列表或dict以外的内容调用
collatz\u seq\u sum
将引发
NotImplementedError

感谢您的输入。嗯,不完全是这样。我根本不想让
collatz\u seq\u sum
seq
的数据类型操心,因为我认为检查数据类型不是
collatz\u seq\u sum
的工作。它的工作是计算总和;没别的。你的意思是说你想让collatz_seq__sum处理任何数据类型,而不检查数据类型吗?是的,这是基本想法,因为我不想在处理数百个函数时进行几乎相同的检查。谢谢你的输入。嗯,不完全是这样。我根本不想让
collatz\u seq\u sum
seq
的数据类型操心,因为我认为检查数据类型不是
collatz\u seq\u sum
的工作。它的工作是计算总和;没别的。你的意思是说你想让collatz_seq__sum处理任何数据类型,而不检查数据类型吗?是的,这是基本想法,因为我不想在处理数百个函数时进行几乎相同的检查。谢谢你的输入。这是一个很好的论点,我理解。我只是在想:这是唯一的方法吗?假设您使用的脚本使用了成百上千的函数。我的意思是,它总是一次又一次地重复相同的事情:每个函数检查其参数的类型,并相应地执行操作。一次又一次地做同样的事情会变得极其乏味,而且我认为很难阅读和维护。这就是类(和duck类型)的用途。这就是python的哲学思想。感谢您的输入。这是一个很好的论点,我理解。我只是在想:这是唯一的方法吗?假设您使用的脚本使用了成百上千的函数。我的意思是,它总是一次又一次地重复相同的事情:每个函数检查其参数的类型,并相应地执行操作。一次又一次地做同样的事情会变得极其乏味,而且我认为很难阅读和维护。这就是类(和duck类型)的用途。这就是python的原理