将functor创建为可调用类或嵌套函数

时间:2016-01-19 10:51:03

标签: python python-3.x coding-style

在Python 3中,您可以创建如下类:

class foo:
    def __init__(self, x):
        self.x=x

    def __call__(self, y):
        self.x = self.x + 1
        return (self.x, y)

然后可以将它用作具有如下状态的仿函数:

functor = foo(5)
x = 44354234
print('(1.1) ', functor(7))
print('(1.2) ', functor(8))
print('(1.2) ', functor(9))

在实践中,我创建了一个返回函数的函数。但是,第一个函数实际上是一个返回可调用对象的构造函数。恕我直言通过允许开发人员扩展类,添加方法等等来打开一堆蠕虫。此外,__init__中的代码自然会先于__call__中的代码,因为它需要执行,并且在类构造中并不清楚。最后,Python 3'方式'建议在类上使用函数。

由于这个原因,我创建了一个类似的函数版本,它具有较少的样板代码和恕我直言的读取更自然:

def bar(x):
    def f(y):
        nonlocal x
        x = x + 1
        return (x,y)
    return f

functor2 = bar(5)
x = 345234234
print('(2.1) ', functor2(7))
print('(2.2) ', functor2(8))
print('(2.3) ', functor2(9))

然而,它使用nonlocal并且由于我没有想到的原因可能不直观。第二种方法是良好的做法,还是有危险的窖藏?哪个应该是Python 3的首选?特别是因为我对nonlocal的使用经验很少。

1 个答案:

答案 0 :(得分:1)

近年来,Python开发策略看起来像是“让我们在Python中融入其他语言的每个功能”,这样就能够以各种方式完成单个任务。

因此,做某些事情真的没有“首选方式”,这完全取决于开发人员想要做什么。因此,在某些情况下可能需要使用Class来创建有状态函数并允许扩展它。使用nonlocal闭包是更常见的IMO,并且没有任何不直观的内容。另一个问题是,当将这种方法用于方法装饰器时,那么使用函数就必须编写更少的代码,而对于类,由于self,你必须添加更多“魔法”。

P.S。在Python中,函数可以具有属性,因此使用x作为f内部函数的属性而不是nonlocal的另一种方法是使用def bar(x): def f(y): f.x=f.x+1 return (f.x, y) f.x=x return f ,尽管它不那么常见你。

SELECT 
    projects_tasks.id AS task_id,
    projects_tasks.name AS task_name,
    projects_tasks.created_by AS task_creator,
    labels.name AS task_label,
    users.name AS task_responsible_name,
    users.surname AS task_responsible_surname,
    users2.name AS task_assigner_name,
    users2.surname AS task_assigner_surname,
    (CASE WHEN projects_tasks_deadlines.deadline_active = '1' THEN projects_tasks_deadlines.deadline ELSE projects_tasks.deadline END) AS task_deadline
FROM projects_tasks
    INNER JOIN `labels` ON labels.id = projects_tasks.label_id
    INNER JOIN `users` ON users.id = projects_tasks.responsible_id
    INNER JOIN `users` AS `users2` ON users2.id = projects_tasks.created_by
    LEFT JOIN projects_tasks_deadlines ON projects_tasks_deadlines.task_id = projects_tasks.id
WHERE projects_tasks.project_id = '1'
AND labels.id != '8'
GROUP BY projects_tasks.id
ORDER BY CASE WHEN projects_tasks_deadlines.deadline_active = '1' THEN -projects_tasks_deadlines.deadline ELSE -projects_tasks.deadline END DESC

编辑:为返回语句添加了额外的缩进