可以用python修饰符更改类(类型)的名称吗?

2024-05-15 23:15:20 发布

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

我试图通过装饰我的Django(ORM)模型(类定义)来自动编码100个数据库表模型,从而从文件名中派生出它们的类名。但我觉得我的“装饰深度”太浅了。我需要在我的__call__方法中使用函数def或类定义吗?像这样简单的事情就做不到吗?在

# decorators.py
import os
from inspect import get_module

class prefix_model_name_with_filename(object):
    'Decorator to prefix the class __name__ with the *.pyc file name'

    def __init__(self, sep=None):
        self.sep = sep or ''

    def __call__(self, cls):
        model_name = os.path.basename(getmodule(cls).__file__).split('.')[0]
        setattr(cls, '__name__', model_name + self.sep + getattr(cls, '__name__'))
        return cls

decorator的示例用法

^{pr2}$

模型不存在于具有新名称的模块定义中,并且我不能使用它而不在decorator类(而不是model类)中查找属性!在

>>> from sec_mirror.models import ShipMeth
>>> ShipMeth.__name__

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/home/Hobson/.virtualenvs/dev/lib/python2.7/site-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 ShipMeth.__name__

AttributeError: 'prefix_model_name_with_filename' object has no attribute '__name__'

我需要装点模块吗?在


Tags: name模型importselfprefixmodel定义os
2条回答

您使用类本身作为装饰器,因此只调用它的__init__。你的__call__永远不会被调用。在

请改用实例:

@decorators.prefix_model_name_with_filename()

关于您更新的问题:decorator不能更改用于引用封闭命名空间中对象的实际名称。(您可以通过将一个新名称粘贴到特定的名称空间中来强制执行此操作,但这取决于您确保将名称放入其中的名称空间是最初定义对象的名称空间。)decorator语法:

^{pr2}$

相当于

class Foo(object):
    ...
Foo = deco(Foo)

注意最后一行是Foo =,因为原始类是用class Foo定义的。你不能改变这一点。装饰后的对象总是重新指定为它原来的名称。在

有一些老掉牙的方法来解决这个问题。您可以让decorator向全局名称空间写入一个新名称,甚至可以查看修饰对象的__module__属性并向该名称空间写入一个新名称。然而,这并不是decorator的真正目的,它会使代码变得混乱。decorator用于修改/包装对象,而不是修改从中访问这些对象的命名空间。在

也许这就是元类的工作:

import os

def cls_changer(name, parents, attrs):
    model_name = os.path.basename(__file__).split('.')[0]
    return type(model_name+name, parents, attrs)

class A(object):
    __metaclass__ = cls_changer
    pass

print A.__name__

上一个示例只创建名称已更改的新类,但如果您希望模块反映您对此所需的更改(请注意,我的python脚本名为untitled0.py):

^{pr2}$

输出:

untitled0A
<class '__main__.untitled0A'>

相关问题 更多 >