为清晰起见,已编辑:
我正在尝试解决导致错误的category
None
问题:TypeError: Incompatible collection type: None is not list-like
我正在尝试检查在创建此对象category
的实例时是否有字符串,int或对象,以便通过表中的ORM传递它。我一直遇到一个错误(如上所示),所以我想创建一个检查,让对象通过,如果它们是对象。
我一直在重做的代码,但并没有完全按照我希望的那样做。任何帮助/解释都将非常感激!
这里的课程
class BaseAPI(object):
def create_element(self, element_text, category): # OBJ
new_element = Element(element_text, category)
self.session.add(new_element)
self.session.commit()
print(element_text)
class ConvenienceAPI(BaseAPI):
def create_element(self, element_text, category_name):
category = category_name
if type(category) == str:
category = self.retrieve_category(category_name)
elif type(category) == int:
print('Sorry integers not accepted')
else:
return super(ConvenienceAPI, self).create_element(element_text, category)
在test.py文件中,我创建了元素和类别的两个实例:
api = ConvenienceAPI()
sa = api.create_category('Situation Awareness')
api.create_element('gathering information', sa)
api.create_category('Leadership')
api.create_element('gathering information', 'Leadership')
运行test.py后ADDED TRACEBACK ERROR:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/Users/ack/code/venv/NotssDB/notssdb/test/test.py", line 41, in test1
sa3 = api.create_element('projecting and anticipating future state', sa)
File "/Users/ack/code/venv/NotssDB/notssdb/api/convenience.py", line 22, in create_element
return super(ConvenienceAPI, self).create_element(element_text, category)
File "/Users/ack/code/venv/NotssDB/notssdb/api/object.py", line 192, in create_element
new_element = Element(element_text, category)
File "<string>", line 4, in __init__
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/state.py", line 306, in _initialize_instance
manager.dispatch.init_failure(self, args, kwargs)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/state.py", line 303, in _initialize_instance
return manager.original_init(*mixed[1:], **kwargs)
File "/Users/ack/code/venv/NotssDB/notssdb/model/base.py", line 180, in __init__
self.category = category
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 224, in __set__
instance_dict(instance), value, None)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 1022, in set
lambda adapter, i: adapter.adapt_like_to_iterable(i))
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 1038, in _set_iterable
new_values = list(adapter(new_collection, iterable))
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py", line 1022, in <lambda>
lambda adapter, i: adapter.adapt_like_to_iterable(i))
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/collections.py", line 636, in adapt_like_to_iterable
given, wanted))
TypeError: Incompatible collection type: None is not list-like
-------------------- >> begin captured stdout << ---------------------
--start db Session--
Situation Awareness
(u'Leadership', 1)
答案 0 :(得分:1)
在test.py的第一个测试用例中:
sa = api.create_category('Situation Awareness')
api.create_element('gathering information', sa)
sa
等于函数api.create_category()
的返回值。我将假设此函数没有定义的返回值,这将导致sa
为None
。你在该测试的下一行真正调用的是api.create_element('gathering information', None)
,当你期望可迭代的东西时,会导致意外类型的'None'被传递给sqlalchemy。
create_category()
的结果分配给变量,因为没有任何变量,而是以与领导示例相同的方式使用API。基本上不要做与sa = api.create_category('Situation Awareness')
create_category()
函数以返回其输入类别。例如,create_category("Situation Awareness")
应返回“情境意识”,而不是None
。类型安全。你假设传递的变量类型不一定是真的。特别要看:
class ConvenienceAPI(BaseAPI):
def create_element(self, element_text, category_name):
category = category_name
if type(category) == str:
category = self.retrieve_category(category_name)
elif type(category) == int:
print('Sorry integers not accepted')
else:
return super(ConvenienceAPI, self).create_element(element_text, category)
假设在else:
子句中,category
是某种类型的对象。但正如您所看到的,只要category
不是str,int或对象,您就会立即得到错误。而这仍然留下了BaseAPI期望的对象类型的问题。
可能的解决方案:
class ConvenienceAPI(BaseAPI):
def create_element(self, element_text, category_name):
category = category_name
# if category is None, then this will fail
# and print out the type (since None evaluates to False).
if category:
if isinstance(category, basestring):
category = self.retrieve_category(category_name)
# Is int and float the only numeric types that can happen?
elif isinstance(category, int) or isinstance(float) :
print('Sorry integers not accepted')
else:
# Danger Zone!!
return super(ConvenienceAPI, self).create_element(element_text, category)
else:
print('Sorry, category is type %s' % str(type(category)))
请注意,我们正在检查basestring
而非str
。这是因为category
可能是unicode,它是有效文本,但它不是str
。 str
和unicode
都是basestring
的子类。有关详细信息,请阅读https://stackoverflow.com/a/152596/5249060。
即使您采取了此修复措施,如果类别不是str
或int
,那么危险区域会发生什么?如果它是一个对象会发生什么,但不是BaseAPI期望的那种?我将在这里停止这个答案,因为有几个选项可以解决这个问题。
为了澄清我之前的一些编辑和评论,您帮助此代码的方法之一是为category
创建一个默认对象,如果它不是str
,{{1或某种对象,而不是记录错误消息。但是,这实际上取决于您正在处理的是否存在可接受的默认值。
答案 1 :(得分:1)
我知道,正如我对其他答案的赞成表明,这与你的问题有些相关。尽管如此,我认为您检查类型的方式是错误的(您报告的类型至少已部分更正)。我将把这个程序留在这里供你考虑:
"""
Exploration of type testing in Python.
"""
def type_test(x):
"""
Reject strings, numbers, and None. Other objects pass through.
"""
if x is None:
return 'Must pass an object: None given.'
try:
float(x)
except ValueError:
if isinstance(x, basestring):
return 'String types are not accepted.'
else:
return x
else:
return 'Numeric types are not accepted.'
def bad_string_test(x):
"""
Only testing for 'str' type lets unicode fall through.
"""
if isinstance(x, str) or type(x) == str or type(x) is str:
return 'Strings are not accepted.'
return x
def bad_numeric_test(x):
"""
Only testing for 'int' or even 'int' and 'float' fails
for numeric types like decimal.Decimal
"""
if isinstance(x, int) or type(x) == int or type(x) is int:
return 'Integers are not accepted.'
elif isinstance(x, float) or type(x) == float or type(x) is float:
return 'Floats are not accepted.'
return x
if __name__ == '__main__':
from decimal import Decimal
print "bad_string_test('Hello') ->", bad_string_test('Hello')
print "bad_string_test(u'Hello') ->", bad_string_test(u'Hello')
print "type_test('Hello') ->", type_test('Hello')
print "type_test(u'Hello') ->", type_test(u'Hello')
print "bad_numeric_test(1) ->", bad_numeric_test(1)
print "bad_numeric_test(1.0) ->", bad_numeric_test(1.0)
print "bad_numeric_test(Decimal('1.0')) ->",\
bad_numeric_test(Decimal('1.0'))
print "type_test(1) ->", type_test(1)
print "type_test(1.0) ->", type_test(1.0)
print "type_test(Decimal('1.0')) ->", type_test(Decimal('1.0'))
print "type_test(None) ->", type_test(None)
输出:
bad_string_test('Hello') -> Strings are not accepted.
bad_string_test(u'Hello') -> Hello
type_test('Hello') -> String types are not accepted.
type_test(u'Hello') -> String types are not accepted.
bad_numeric_test(1) -> Integers are not accepted.
bad_numeric_test(1.0) -> Floats are not accepted.
bad_numeric_test(Decimal('1.0')) -> 1.0
type_test(1) -> Numeric types are not accepted.
type_test(1.0) -> Numeric types are not accepted.
type_test(Decimal('1.0')) -> Numeric types are not accepted.
type_test(None) -> Must pass an object: None given.
需要注意的事项:
我们不是试图枚举所有数字类型,而是尝试使用强制转换来浮动,将失败解释为对象是“数字类型”。这会投出更广泛的网络,并且还会选择decimal.Decimal
这样的内容,我认为您也希望排除它。
type_test
包含明确的None
测试。这是必需的,因为float(None)
会引发TypeError
,您基本上不想抓住它。