验证参数是序列而不是字符串的 Pythonic 方法
我有一个函数,它获取数据库表列表作为参数,并返回要在这些表上执行的命令字符串,例如:
pg_dump( file='/tmp/dump.sql',
tables=('stack', 'overflow'),
port=5434
name=europe)
应该返回类似以下内容:
pg_dump -t stack -t overflow -f /tmp/dump.sql -p 5434 europe
这是使用 tables_string='-t '+' -t 完成的'.join(表)
。
当使用 tables=('stackoverflow')
(字符串)而不是 tables=('stackoverflow',)
(元组)调用函数时,乐趣就开始了,其结果是:
pg_dump -t s -t t -t a -t c -t k -t o -t v -t e -t r -t f -t l -t o -t w
-f /tmp/dump.sql -p 5434 europe
因为字符串本身正在被迭代。
这个问题 建议在类型上使用断言,但我不确定它是否足够Pythonic,因为它打破了鸭子类型约定。
有什么见解吗?
亚当
I have a function that gets a list of DB tables as parameter, and returns a command string to be executed on these tables, e.g.:
pg_dump( file='/tmp/dump.sql',
tables=('stack', 'overflow'),
port=5434
name=europe)
Should return something like:
pg_dump -t stack -t overflow -f /tmp/dump.sql -p 5434 europe
This is done using tables_string='-t '+' -t '.join(tables)
.
The fun begins when the function is called with: tables=('stackoverflow')
(a string) instead of tables=('stackoverflow',)
(a tuple), which yields:
pg_dump -t s -t t -t a -t c -t k -t o -t v -t e -t r -t f -t l -t o -t w
-f /tmp/dump.sql -p 5434 europe
Because the string itself is being iterated.
This SO question suggests using asserts on the type, but I'm not sure it's Pythonic enough because it breaks the duck-type convention.
Any insights?
Adam
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在这种情况下断言类型似乎是合适的——处理由于鸭子类型而看似合法的常见误用。
处理这种常见情况的另一种方法是测试字符串并将其作为特殊情况正确处理。
最后,您可以鼓励将表名称作为位置参数传递,这将减少这种情况的发生:
Asserting the type seems appropriate in this case - handling a common misuse that seems legal because of duck typing.
Another way to handle this common case would be to test for string and handle it correctly as a special case.
Finally, you could encourage passing the table names as positional parameters which would make this scenario less likely:
您可以使用 ABC 断言对象是可迭代的,但不是字符串:
You can use ABCs to assert that an object is iterable but not a string:
检测参数是序列(列表或元组)还是字符串的常见 Python 习惯用法是检查它是否具有 __iter__ 属性:
当它不是序列时,也通常会更改它合并为一个以简化代码的其余部分(只需处理一种事情)。在示例中,可以使用简单的
arg = [arg]
来完成。A common Python idiom to detect whether an argument is a sequence (a list or tuple) or a string is to check whether it has the
__iter__
attribute:When it's not a sequence, it's also common to change it into one to simplify the rest of the code (which only has to deal with one kind of thing). In the sample it could have been done with a simple
arg = [arg]
.不能使用列表而不是元组吗?
Can you not use a list rather than a tuple?
我能想到的最简洁的方法是通过重写 subclasshook 创建一个新的抽象集合类型“NonStrSequence”。请参阅下面的实现和测试:
The cleanest way I can think of is to create a new Abstract Collection type "NonStrSequence" by overriding subclasshook. See below implementation and tests: