Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以使用python装饰器更改类(类型)的名称?_Python_Django_Class_Python Decorators - Fatal编程技术网

是否可以使用python装饰器更改类(类型)的名称?

是否可以使用python装饰器更改类(类型)的名称?,python,django,class,python-decorators,Python,Django,Class,Python Decorators,我试图通过装饰我的Django(ORM)模型(类定义)来自动编码100个数据库表模型,以从文件名派生它们的类名。但我觉得我的“装饰深度”太浅了。在我的\uuuu调用\uuuu方法中是否需要函数def或类定义?像这样简单的事情难道不能做到吗 # decorators.py import os from inspect import get_module class prefix_model_name_with_filename(object): 'Decorator to prefix

我试图通过装饰我的Django(ORM)模型(类定义)来自动编码100个数据库表模型,以从文件名派生它们的类名。但我觉得我的“装饰深度”太浅了。在我的
\uuuu调用\uuuu
方法中是否需要函数
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的示例用法

# models.py
from django.db import models
import decorators

@decorators.prefix_model_name_with_filename
class ShipMeth(models.Model):
    ship_meth = models.CharField(max_length=1, primary_key=True)
该模型在模块定义中没有新名称,如果不在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__'
>>来自sec_mirror.models导入ShipMeth
>>>船名__
---------------------------------------------------------------------------
AttributeError回溯(最近一次呼叫上次)
/home/Hobson/.virtualenvs/dev/lib/python2.7/site-packages/django/core/management/commands/shell.pyc in()
---->1船名__
AttributeError:'prefix\u model\u name\u with\u filename'对象没有属性'\uuuuuu name\uuuu'

我是否需要以某种方式装饰模块?

您使用类本身作为装饰器,因此只调用它的
\uuuu init\uuu
。您的
\uuuu调用\uuuu
从未被调用

请改用实例:

@decorators.prefix_model_name_with_filename()
关于您更新的问题:装饰程序无法更改用于引用封闭命名空间中对象的实际名称。(您可以通过将新名称粘贴到特定名称空间中来强制执行,但由您来确保将名称放入的名称空间是最初定义对象的名称空间。)decorator语法:

@deco
class Foo(object):
    ...
相当于

class Foo(object):
    ...
Foo = deco(Foo)
注意,最后一行是
Foo=
,因为原始类是用
class Foo
定义的。你不能改变这一点。装饰对象始终被重新指定给它最初拥有的相同名称


有一些骇人的方法可以绕过这个问题。您可以让装饰器向全局名称空间写入新名称,甚至可以查看装饰对象的
\uuuu模块\uuu
属性,然后向该名称空间写入新名称。然而,这并不是装饰器的真正用途,它会让您的代码变得混乱。decorator用于修改/包装对象,而不是修改从中访问这些对象的名称空间。

您使用类本身作为decorator,因此只调用它的
\uuu init\uuu
。您的
\uuuu调用\uuuu
从未被调用

请改用实例:

@decorators.prefix_model_name_with_filename()
关于您更新的问题:装饰程序无法更改用于引用封闭命名空间中对象的实际名称。(您可以通过将新名称粘贴到特定名称空间中来强制执行,但由您来确保将名称放入的名称空间是最初定义对象的名称空间。)decorator语法:

@deco
class Foo(object):
    ...
相当于

class Foo(object):
    ...
Foo = deco(Foo)
注意,最后一行是
Foo=
,因为原始类是用
class Foo
定义的。你不能改变这一点。装饰对象始终被重新指定给它最初拥有的相同名称


有一些骇人的方法可以绕过这个问题。您可以让装饰器向全局名称空间写入新名称,甚至可以查看装饰对象的
\uuuu模块\uuu
属性,然后向该名称空间写入新名称。然而,这并不是装饰器的真正用途,它会让您的代码变得混乱。装饰器用于修改/包装对象,而不是修改从中访问这些对象的名称空间。

可能这就是元类的工作:

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):

输出:

untitled0A
<class '__main__.untitled0A'>
untitled0A

也许这就是元类的工作:

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):

输出:

untitled0A
<class '__main__.untitled0A'>
untitled0A

修复了我的即时错误。ShipMeth.\uuuuu name\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是,它不会影响模块的locals()dict键(类/类型的实际名称)。所以我还是遗漏了一些东西。我是否需要以某种方式装饰模块?@hobs:查看我的最新答案。你不能用decorator来实现这一点(如果没有丑陋的黑客),我想我只需要一个自动排序器来编写类定义,以便在py文件中输入正确的名称,而不是在所有类的前面加上decorator。事后看来,装饰师的尝试似乎过于复杂。感谢您提醒/教育我什么是装饰师及其局限性。这修正了我的直接错误。ShipMeth.\uuuuu name\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是,它不会影响模块的locals()dict键(类/类型的实际名称)。所以我还是遗漏了一些东西。我是否需要以某种方式装饰模块?@hobs:查看我的最新答案。你不能用decorator来实现这一点(如果没有丑陋的黑客),我想我只需要一个自动排序器来编写类定义,以便在py文件中输入正确的名称,而不是在所有类的前面加上decorator。事后看来,装饰师的尝试似乎过于复杂。感谢您提醒/教育我什么是装饰师及其局限性。可能吧,但我不知道如何使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?。我的意思是:class
class ShipMeth(models.Model):\n\uuuu元类\uuuu=cls\u转换器
Ahh,我明白了。我会试试的。我刚刚注意到你用的是Django!!也许这种方法对你没有帮助,因为Django也使用元类!!所以如果你改变它,也许你会把它搞砸!试着让我知道;