下面是功能范例中的列表抽象,它将任何类型的数据封装在其表示中。
empty_rlist = None
#Representation - start
#Constructor
def rlist(first, rest):
return(first, rest)
#Selector
def first(s):
return s[0]
def rest(s):
return s[1]
#Representation - end
#Constructor and Selector constitutes ADT(above) that supports below invariant:
#If a recursive list s is constructed from a first element f and a recursive list r, then
# • first(s) returns f, and
# • rest(s) returns r, which is a recursive list.
#Usage(interface) - start
def create_list(first, rest):
return rlist(first, rest)
def len_rlist(s):
"""Compute the length of the recursive list s"""
def compute_length(s, length):
if s is empty_rlist:
return length
else:
return compute_length(rest(s), length + 1)
return compute_length(s, 0)
def getitem_rlist(s, i):
"""Return the element at index i of recursive list s"""
if i == 1:
return first(s)
else:
return getitem_rlist(rest(s), i-1)
def count(s, value):
"""Count the occurence of value in the list s """
def count_occurence(s, value, count):
if s == empty_rlist:
return count
else:
if first(s) == value:
return count_occurence(rest(s), value, count + 1)
else:
return count_occurence(rest(s), value, count)
return count_occurence(s, value, 0)
#Usage - end
Lst = empty_rlist
Lst = create_list(4, Lst)
Lst = create_list(3, Lst)
Lst = create_list(1, Lst)
Lst = create_list(1, Lst)
print(count(Lst, 1))
在上面的代码中,提供给此抽象用户的接口是create_list
/ len_rlist
/ getitem_rlist
/ count
。
问题:
如何强制传递给接口s
/ len_rlist
/ getitem_rlist
的参数(count
)的对象只是{create_list
提供的对象。 1}} interface?
如何强制执行以上列表抽象存储相同类型的数据?
注意:实际上,需要从语法角度强制执行这些规则。
答案 0 :(得分:3)
由于python
是动态类型语言,因此您无法在执行前检查类型。但实际上有时需要检查输入参数,返回值。我使用下一个解决方案来完成这项任务:
def accepts(*types):
"""Check input types"""
#print types
def check_accepts(f):
assert len(types) == f.func_code.co_argcount
def new_f(*args, **kwds):
for (a, t) in zip(args, types):
assert isinstance(a, t), \
"arg %r does not match %s" % (a,t)
return f(*args, **kwds)
new_f.func_name = f.func_name
return new_f
return check_accepts
def returns(rtype):
"""Check returns type"""
def check_returns(f):
def new_f(*args, **kwds):
result = f(*args, **kwds)
assert isinstance(result, rtype), \
"return value %r does not match %s" % (result,rtype)
return result
new_f.func_name = f.func_name
return new_f
return check_returns
if __name__ == '__main__':
import types
@returns(types.NoneType) #Check None as result
@accepts(int, (int,float)) #First param int; second int or float
def func(arg1, arg2):
#return str(arg1 * arg2)
pass
func(1, 2)
答案 1 :(得分:0)
Python 不是强类型语言。更准确地说,它是一个动态类型。这意味着变量包含具有类型的值,但语言本身永远不会禁止在变量中放入不同类型的值。
a = 1 # a contains an integer value
a = "abc" # a now contains a string value
但是,你有isinstance
和type
函数可以帮助实现这个要求:你可以影响递归列表的类型,只允许绑定元素和递归列表兼容类型。
完整的规范可能是:
isinstance(elt, typ)
为真的第一个元素来构建rlist,typ
是 rest 部分的可接受的类型实现:
class rlist:
def __init__(self, first, rest=None, typ=None):
self.first = first
self.rest = rest
if rest is None: # initial creation
self.typ = type(first) if typ is None else typ
else:
if not isinstance(rest, rlist):
raise TypeError(str(rest) + " not a rlist"
self.typ = rest.typ
if not isinstance(first, self.typ):
raise TypeError(str(first) + "not a " + str(typ))
# other methods ...
但是当你需要强类型时,你应该想知道Python是否真的是合适的语言 - Java 强类型并且本机支持所有这些。 Python方式更多我接受这个并且只是希望它适合,程序员应该知道他做了什么
答案 2 :(得分:0)
为了强制执行该类型,您必须在构造函数中的某处提供类型作为参数。考虑构建参数化类型构造函数。这是一个例子。
>>> def list_spec_for(type_):
... empty_rlist = type_()
... def rlist(first, rest):
... return (type_(first), rest)
... return empty_rlist, rlist
>>> empty_rlist, rlist = list_spec_for(int)
>>> empty_rlist
0
>>> rlist(1, empty_rlist)
(1, 0)
>>> rlist("1", empty_rlist)
(1, 0)
>>> rlist("one", empty_rlist)
ValueError: invalid literal for int() with base 10: 'one'
如果接受“1”不适合您的目的,您当然可以在rlist的定义中添加isinstance
项检查。