我使用的是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_seq
返回列表的原因。但是,我发现在处理行中的多个参数n
时,观察这个特定序列是如何发展的很有趣。这就是我创建collatz_seqs
。
我不喜欢collatz_seq_sum
的原因非常简单:只有当参数seq
的类型为list
时,它才能正常工作。在我看来,collatz_seq_sum
不负责确保提供适当的实际参数,在这种情况下由list
组成自然数。在我看来,collatz_seq_sum
的来电者必须确保它提供了正确的参数。
我希望collatz_sum_seq
能够处理单个和多个序列。 collatz_seq
返回list
,collatz_seqs
返回dict
。因此,我的问题是:确保collatz_seq_sum
始终为其参数seq
获取正确数据类型的优雅方法是什么?如果collatz_seq_sum
没有collatz_seq_sum
关注其参数seq
的数据类型,我可以做些什么才能正常工作?我的第一个想法是更改collatz_seq
以使其返回dict
而不是list
并更改collatz_seq_sum
以处理dict
。但是,我不喜欢这种方法,因为在处理单个序列时我不想要dict
。
你对此有什么解决方案吗?非常感谢你提前。
答案 0 :(得分:0)
如果我理解正确,你希望collatz_seq_sum
能够同时处理一个关于折叠序列的字典或一个单独的折叠序列。对于字典,您希望函数返回单个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)
答案 1 :(得分:0)
在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
如果你想让一个函数的行为不同,这取决于输入的类型,这是可行的方法。
答案 2 :(得分:0)
Python 3.4+ - functools.singledispatch允许你根据参数的类型重载一个函数定义。
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_seq_sum
会引发NotImplementedError
。