在尝试在Python中实现C-for循环之后,开发了以下函数:
import sys
def rof(init, cond, post):
init, cond, post, context = compile(init, '<rof>', 'exec'), \
compile(cond, '<rof>', 'eval'), \
compile(post, '<rof>', 'exec'), \
sys._getframe(1)
context = context.f_globals, context.f_locals
exec(init, *context)
while eval(cond, *context):
yield None
exec(post, *context)
正如任何程序员所知,需要测试新函数,以确保其工作:
设置
class Employee:
def __init__(self, employee_id, category, hired, salary, years):
vars(self).update(locals())
def __repr__(self):
return '{}({})'.format(self.__class__.__name__,
', '.join(map(repr, self)))
def __iter__(self):
yield self.employee_id
yield self.category
yield self.hired
yield self.salary
yield self.years
database = [Employee(123, 'P', 2014, 2000, 0),
Employee(234, 'F', 2000, 20000, 14),
Employee(123, 'F', 2010, 10000, 4)]
在某些情况下(如以下情况),代码运行时不会出错:
试用版1
for _ in rof('a = 0', 'a < len(database)', 'a += 1'):
employee_id = database[a].employee_id
for _ in rof('b = len(database) - 1', 'b > a', 'b -= 1'):
if database[b].employee_id == employee_id:
print(database[b], 'is being removed.')
del database[b]
但是,当循环位于单独的函数中时,它不起作用。你知道吗
试用版2
def remove_duplicates(database):
a = b = int
for _ in rof('a = 0', 'a < len(database)', 'a += 1'):
employee_id = database[a].employee_id
for _ in rof('b = len(database) - 1', 'b > a', 'b -= 1'):
if database[b].employee_id == employee_id:
print(database[b], 'is being removed.')
del database[b]
remove_duplicates(database)
而是生成一个错误(TypeError: list indices must be integers, not type
)。你知道吗
我们都同意这段代码不是Pythonic的,但是有人能确定是什么导致了这个问题以及如何修复它吗?你知道吗
在python3中,不可能在
locals()
中创建新的局部变量,因为在编译时会扣除局部变量集。特别是如果您修改remove_duplicates
,使其不具有a = b = int
行,Python不会将这些名称视为引用局部变量,而是全局变量。有了这条线,它们就被认为是一个局部变量,是的。你知道吗另外,通过frame对象更改局部变量是不可能的,因为在python3中,局部变量不再存储在字典中。相反,在cpython3上,
frame.f_locals
访问使用PyFrame_FastToLocals
创建变量的副本,但通常是单向的。因此,虽然您可以读取变量的值,但不会传播任何更改,a
和b
继续is int
。但是(module)全局变量仍然存储在一个字典中,该字典可以通过frame.f_globals
直接访问;并且字典是开放的,可以进行更改。你知道吗然而,PyDev维护人员对如何在cpython3上实现这一点还有a blog post。因此,下面的
rof
实现似乎为我实现了技巧:我认为这是一个可憎的代码,如果有什么,并建议,而不是这个,假设程序员将知道如何改变一个C for循环变成一个C while循环。。。然后把它转化成Python。不管怎样,如果不给函数体中的这些变量赋予初始值,它仍然无法工作。你知道吗
因此,我提出了另一种
rof
实现:印刷品:
这是应该写的。你知道吗
虽然在这种情况下没有什么错:
相关问题 更多 >
编程相关推荐