不久前我正在研究的一个功能是这样的结构:
def function():
class Inner:
#class stuff
#function stuff
Inner
仅在function
内使用和需要,并且在函数末尾也不会返回。定义本地课程是一个坏主意吗?我已经听过很多关于它如何对性能有害的事情,因为python必须在每次运行函数时重新编译类,并且由于性能是我打算用这个函数实现的,我有点担心这样做
答案 0 :(得分:3)
不是那么重新编译,而是重新评估。一个简单的测试是制作这样的模块:
class Root(object):
print("root")
def make_inner():
class Inner(object):
print("inner")
return Inner()
print("importing")
然后尝试运行此
>>> import inner
root
importing
>>> import inner
>>> inner.make_inner()
inner
<inner.Inner object at 0x12efad0>
>>> inner.make_inner()
inner
<inner.Inner object at 0x12efb50>
>>>
>>> reload(inner)
root
importing
<module 'inner' from 'inner.pyc'>
基本上,您可以看到每次调用make_inner
时都会执行类定义。如果在循环中调用该特定函数,这可能是一个问题,例如,它几乎就像重新加载类定义一样,但实际上并非如此。
答案 1 :(得分:3)
除了效率低下之外,每个Inner
类都是一个全新的对象,因此单独的实例永远不会是同一个类,这在某种程度上违背了类的含义:
In [4]: def factory():
...: class Inner(object):
...: pass
...: return Inner
...:
In [5]: i1 = factory()()
In [6]: i2 = factory()()
In [7]: i1.__class__
Out[7]: __main__.Inner
In [8]: i2.__class__
Out[8]: __main__.Inner
In [9]: i1.__class__ is i2.__class__
Out[9]: False
In [10]: isinstance(i1, i2.__class__)
Out[10]: False
如果每个实例完全独立,这不是问题,但需要注意的事项。
答案 2 :(得分:1)
在你的案例中定义一个本地类似乎没用。如果 定义本地类时有一些缺点:
定义本地类也有一些优点:
我的建议是简单地全局定义类,如果它应该是私有的,则使用以下划线开头的名称,如_MyClass
,因为这是用于表示私有项的约定。
了解绩效变化的一些时间:
In [1]: class _Out(object):
...: def test(self):
...: for _ in range(10):
...: pass
...:
In [2]: def function_out(n):
...: for _ in range(n):
...: _Out().test()
...:
In [3]: def function_in(n):
...: class Inner(object):
...: def test(self):
...: for _ in range(10):
...: pass
...: for _ in range(n):
...: Inner().test()
...:
In [4]: def function_mixed(n, cls=_Out):
...: # use of default to access the global class via local variable
...: for _ in range(n):
...: cls().test()
...:
In [5]: %timeit function_out(1000)
1000 loops, best of 3: 602 us per loop
In [6]: %timeit function_in(1000)
1000 loops, best of 3: 621 us per loop
In [7]: %timeit function_mixed(1000)
1000 loops, best of 3: 590 us per loop
In [8]: %timeit function_out(100000)
10 loops, best of 3: 59.9 ms per loop
In [9]: %timeit function_in(100000)
10 loops, best of 3: 60.2 ms per loop
In [10]: %timeit function_mixed(100000)
10 loops, best of 3: 58.4 ms per loop
In [11]: %timeit function_out(10)
100000 loops, best of 3: 6.52 us per loop
In [12]: %timeit function_in(10)
10000 loops, best of 3: 57.8 us per loop
In [13]: %timeit function_mixed(10)
100000 loops, best of 3: 6.33 us per loop
请注意,大量迭代function_in
和function_out
大约在同一时间运行,而迭代次数较少function_in
大约慢10倍。