有方法isiterable吗?到目前为止我找到的唯一解决方案是打电话
hasattr(myObj, '__iter__')
Run Code Online (Sandbox Code Playgroud)
但我不确定这是多么万无一失.
可以说我有两个功能:
def foo():
return 'foo'
def bar():
yield 'bar'
Run Code Online (Sandbox Code Playgroud)
第一个是正常函数,第二个是生成器函数.现在我想写这样的东西:
def run(func):
if is_generator_function(func):
gen = func()
gen.next()
#... run the generator ...
else:
func()
Run Code Online (Sandbox Code Playgroud)
什么是直截了当的实现is_generator_function()?使用types包我可以测试是否 gen是生成器,但我希望在调用之前这样做func().
现在考虑以下情况:
def goo():
if False:
yield
else:
return
Run Code Online (Sandbox Code Playgroud)
调用goo()将返回生成器.我假设python解析器知道该goo()函数有一个yield语句,我想知道是否可以轻松获取该信息.
谢谢!
作为一个完整的Python新手,它肯定是这样的.运行以下...
x = enumerate(['fee', 'fie', 'foe'])
x.next()
# Out[1]: (0, 'fee')
list(x)
# Out[2]: [(1, 'fie'), (2, 'foe')]
list(x)
# Out[3]: []
Run Code Online (Sandbox Code Playgroud)
......我注意到:(a)x确实有一个next方法,似乎是生成器所需要的,而(b)x只能迭代一次,这个着名的python标签答案中强调了生成器的一个特征.
在另一方面,这两个最高度upvoted回答这个问题,
如何确定一个对象是否是发电机似乎表明,enumerate()它不会返回发电机.
import types
import inspect
x = enumerate(['fee', 'fie', 'foe'])
isinstance(x, types.GeneratorType)
# Out[4]: False
inspect.isgenerator(x)
# Out[5]: False
Run Code Online (Sandbox Code Playgroud)
......虽然对该问题的第三个低调的回答似乎表明实际上enumerate() 确实返回了一个发电机:
def isgenerator(iterable):
return hasattr(iterable,'__iter__') and not hasattr(iterable,'__len__')
isgenerator(x)
# Out[8]: True
Run Code Online (Sandbox Code Playgroud)
发生什么了?是x发电机还是没有?它在某种意义上是"类似发电机",但不是真正的发电机吗?Python使用duck-typing是否意味着上面最后一个代码块中概述的测试实际上是最好的?
我不会继续写下我头脑中可能存在的可能性,而是将其抛给那些立即知道答案的人.
假设我有以下函数:
def print_twice(x):
for i in x: print(i)
for i in x: print(i)
Run Code Online (Sandbox Code Playgroud)
当我跑步时:
print_twice([1,2,3])
Run Code Online (Sandbox Code Playgroud)
或者:
print_twice((1,2,3))
Run Code Online (Sandbox Code Playgroud)
我得到了预期的结果:数字 1,2,3 被打印两次。
但是当我跑步时:
print_twice(zip([1,2,3],[4,5,6]))
Run Code Online (Sandbox Code Playgroud)
(1,4),(2,5),(3,6) 对仅打印一次。可能这是因为zip返回一个在一次传递后终止的生成器。
如何修改该函数print_twice以使其正确处理所有输入?
我可以在函数的开头插入一行:x = list(x)。但如果 x 已经是列表、元组、范围或任何其他可以迭代多次的迭代器,这可能会效率低下。有更有效的解决方案吗?
假设我有一个有副作用的函数(在这个例子中,副作用是打印了一些东西)。是否有任何版本的 any() 或列表可迭代的任何构造在找到 True 结果后不会触发副作用?
例如,假设这个函数:
def a(x):
print("A function got: " + str(x))
return x == 2
Run Code Online (Sandbox Code Playgroud)
人们可能希望这个电话能奏效。当然,它不会:
any([
a(i) for i in range(5)
])
Run Code Online (Sandbox Code Playgroud)
哪个打印:
A function got: 0
A function got: 1
A function got: 2
A function got: 3
A function got: 4
Run Code Online (Sandbox Code Playgroud)
但我希望它打印出来:
A function got: 0
A function got: 1
A function got: 2
Run Code Online (Sandbox Code Playgroud)
为什么?Range 是一个可迭代的,列表推导正在产生一个可迭代的,我有点希望 Python 将它们链接在一起并在 any() 函数停止消耗后立即停止执行整个事情,一旦它达到第一个 True 就应该这样做.
我有什么误解?如果有的话,哪个版本会以这种方式运行?
是否有用于内省生成器对象的技术(例如单元测试中的断言)?
更具体地说,我有一个数据处理管道,由一系列小函数组成,这些函数通常应用于列表理解或生成器表达式内的值,如下所示:
生成一些随机数据:
>>> raw_data = ["${}".format(RND.randint(10, 100)) for c in range(10)]
>>> # a function that does some sort of of transform
>>> fnx = lambda q: float(q.replace('$', ''))
>>> d1 = [fnx(itm) for itm in raw_data]
Run Code Online (Sandbox Code Playgroud)
在下一步中,另一个变换函数将应用于d1的项目,依此类推。
在上面的例子中,例如,关于prices_clean的长度或其值的最小/最大等的断言是我的单元测试套件的核心:
>>> assert len(d1) == 10
Run Code Online (Sandbox Code Playgroud)
鉴于我只是要迭代这些中间结果,我实际上不需要列表,生成器对象就可以了,并且考虑到内存配置文件要低得多,这就是我使用的:
>>> d1 = (fnx(itm) for itm in raw_data)
Run Code Online (Sandbox Code Playgroud)
当然,我在使用列表推导式时所依赖的断言不适用于生成器对象:
>>> d1
<generator object <genexpr> at 0x106da9230>
>>> assert len(d1) == 10
Traceback (most recent call last):
File "<pyshell#33>", line 1, …Run Code Online (Sandbox Code Playgroud) 假设我只有1GB的内存和1TB的硬盘空间。
这是我的代码,我正在使用postgres数据库。
import psycopg2
try:
db = psycopg2.connect("database parameters")
conn = db.cursor()
conn.execute(query)
#At this point, i am running
for row in conn:
Run Code Online (Sandbox Code Playgroud)
对于这种情况,我想可以肯定地认为conn是一个生成器,因为我似乎无法在线找到确定的答案,并且由于无法承受系统崩溃而无法在自己的环境中尝试使用。
我期望此查询返回的数据超过100 GB
我正在使用python 2.7和psycopg2库
python ×7
generator ×2
assertion ×1
coroutine ×1
database ×1
function ×1
iterable ×1
postgresql ×1
unit-testing ×1