函数中定义的Python类的状态

2024-04-25 00:36:38 发布

您现在位置:Python中文网/ 问答频道 /正文

def myfn():
    class MyClass:
        pass


    return MyClass()


a = myfn()
b = myfn()

print(type(a) is type(b))

这里我们可以看到type(a)不是type(b)。总是这样吗?既然MyClass的定义不依赖于传递给myfn的任何参数,那么解释程序为什么不对此进行优化呢?你知道吗


Tags: 参数return定义isdeftypemyclasspass
1条回答
网友
1楼 · 发布于 2024-04-25 00:36:38

执行class语句时,总是创建一个新的类对象。类不是单例。通过将class语句放入函数中,您可以多次执行它。你知道吗

模块级的类语句只执行一次,因为在第一次导入时,模块只执行一次。你知道吗

您可以通过从sys.modules结构中删除module对象来绕过此问题;您将注意到第三次导入的Foo类在我们删除模块后是另一个对象:

>>> with open('demomodule.py', 'w') as demomodule:
...     demomodule.write('class Foo: pass\n')
...
16
>>> import sys
>>> from demomodule import Foo  # first import
>>> id(Foo)
140579578254536
>>> import demomodule  # just another reference, module is not run again
>>> id(demomodule.Foo)
140579578254536
>>> del sys.modules['demomodule']  # removing the module object
>>> import demomodule              # this causes it to be imported again
>>> id(demomodule.Foo)
140579574812488

当您以脚本形式运行模块,然后使用import导入相同的模块时,也会发生同样的情况;脚本以__main__模块形式运行,使用import再次导入脚本,然后还为导入的名称创建单独的模块对象:

$ echo 'class Foo: pass
> import demomodule
> print(__name__, id(Foo), id(demomodule.Foo))
> ' > demomodule.py
$ python demomodule.py
demomodule 140718182184264 140718182184264
__main__ 140718182074440 140718182184264

Python本质上是高度动态的;应用优化(比如缓存函数生成的类对象)充满了问题。您的函数可能不接受任何参数,但它不是在真空中运行的。例如,我可以替换__build_class__hook函数,并将一个额外的类插入Python中任何地方创建的类的基中:

>>> def foo_class():
...     class Foo: pass
...     return Foo
...
>>> foo_class().__mro__
(<class '__main__.foo_class.<locals>.Foo'>, <class 'object'>)
>>> import builtins
>>> class Bar: pass
>>> orig_buildclass = builtins.__build_class__
>>> def my_buildclass(f, name, *bases, **kwargs):
...     return orig_buildclass(f, name, *((Bar,) + bases), **kwargs)
...
>>> builtins.__build_class__ = my_buildclass
>>> foo_class().__mro__
(<class '__main__.foo_class.<locals>.Foo'>, <class '__main__.Bar'>, <class 'object'>)

Python中充满了这样的钩子。你知道吗

相关问题 更多 >