Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.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类的Str方法,该方法重新构造类源_Python_Python 2.7_Fixtures_Quine - Fatal编程技术网

用于python类的Str方法,该方法重新构造类源

用于python类的Str方法,该方法重新构造类源,python,python-2.7,fixtures,quine,Python,Python 2.7,Fixtures,Quine,如何为类配备打印类本身的源(不包括方法定义)的\uuu str\uu方法 我排除方法定义,因为我的用例是动态生成装置(使用fixtures包;这与django装置不同),我希望将这些装置存储在文件中。对于那些不知道的人来说,fixtures包使用python类来表示fixture数据 这似乎是一种甚至可以内置到fixture中的东西,因为在我看来,这将是一个中等常见的用例。您可以使用元类来实现这一点。这里我省略了private(以下划线开头)和可调用对象(方法、内部类等)。只包括直接在类上定义的

如何为类配备打印类本身的源(不包括方法定义)的
\uuu str\uu
方法

我排除方法定义,因为我的用例是动态生成装置(使用
fixtures
包;这与django装置不同),我希望将这些装置存储在文件中。对于那些不知道的人来说,
fixtures
包使用python类来表示fixture数据


这似乎是一种甚至可以内置到fixture中的东西,因为在我看来,这将是一个中等常见的用例。

您可以使用元类来实现这一点。这里我省略了private(以下划线开头)和可调用对象(方法、内部类等)。只包括直接在类上定义的属性(正确列出了基类,因此这不应该是问题)

在Python 3中,需要以另一种方式指定元类:

class Mine(metaclass=ClassSourceMeta):
    a = 42
    b = 13
请注意,属性需要具有合理的
repr()
s。如果它们是类实例,你可能会得到语法上无效的东西,比如
a=
,除非你为它们编写了一个好的
\uuuuu repr\uuu
方法。对于一些基本的东西,比如数字和字符串,甚至是列表和口述,你都可以

还要注意的是,属性不一定按照定义的顺序出现;属性存储在不保留插入顺序的
dict
中。不过Python不会在意的

如果
fixtures
模块已经使用了一个元类,那么您可能需要从该元类继承而不是
type
,或者对其元类进行monkey-patch。在Python2.x上,这将需要为
\uuu str\uu
类制作一个方法包装器:

from types import MethodType

def __str__(cls):
     return "class %s(%s):\n\n%s\n" % (cls.__name__, 
            ", ".join(k.__name__ for k in cls.__bases__), 
            "\n".join("    %s = %r" % (k, v) for (k, v) in
            cls.__dict__.items() if not (k.startswith("_") or callable(v))))

 MetaclassToPatch.__str__ = MethodType(__str__, None, MetaclassToPatch)
 MetaclassToPatch.__repr__ = MetaclassToPatch.__str__

您是否查看了
inspect
模块中的相关功能?这将是一个很好的起点。您可能需要检索类的源代码并手动删除方法定义。如果在执行此操作时遇到问题,您可以提出一个更具体的问题来说明您的尝试。不确定这是否是您所要求的,但inspect模块有一个inspect.getsource(obj)方法,该方法可能就是您所寻找的。虽然我不确定它有哪些依赖项才能读取该源代码。动态生成要作为代码执行的文本?我通常认为这是错误的方法。诸如继承、闭包、
eval()
compile()
等似乎涵盖了大多数/所有动态环境用例。设备在存储时是否需要人类可读?如果没有,为什么不直接腌制它们呢?@JAB对于那些不知道的人来说,fixtures包使用python类来表示fixture数据。太棒了,谢谢!为了处理内部类(fixtures模块使用内部类来表示数据库行/实例,其中内部类包含键值对),我还需要对此进行一些处理。我意识到我的问题中没有明确说明内部类的情况。事实上,我可以为外部类和内部类使用不同的元类来干净地完成这项工作。。。基本上给他们相同的元类,然后你必须有一些代码来缩进他们。不幸的是,如果你这么做的话,我认为我的一句话是不可行的。事实上,这对我不起作用。您的测试代码确实有效。我正在修补现有的元类。呵呵。你可能需要为它做一个方法包装器。午饭后我看看能不能搞定。谢谢。对于我的用例,我通过基于您的方法显式调用函数解决了这个问题,因为我只有两个级别。
from types import MethodType

def __str__(cls):
     return "class %s(%s):\n\n%s\n" % (cls.__name__, 
            ", ".join(k.__name__ for k in cls.__bases__), 
            "\n".join("    %s = %r" % (k, v) for (k, v) in
            cls.__dict__.items() if not (k.startswith("_") or callable(v))))

 MetaclassToPatch.__str__ = MethodType(__str__, None, MetaclassToPatch)
 MetaclassToPatch.__repr__ = MetaclassToPatch.__str__