Python如何优雅地处理不同数据结构的使用?
我正在使用Python 3.5,这是我目前正在处理的代码: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
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的原理