Как я могу показать код, который генерируется при использовании декоратора класса @dataclass? - PullRequest
0 голосов
/ 19 ноября 2018

Python 3.7 представляет модуль dataclasses, который содержит декоратор @dataclass.Этот декоратор может генерировать функции класса.Как я могу распечатать эти сгенерированные функции?

1 Ответ

0 голосов
/ 05 июня 2019

Я задавал тот же вопрос сам. Dataclasses проект детали должен иметь подробный параметр, но не является.

Обнаружил это видео , полезно. По данным видео dataclasses.py является генератором кода. Так что это должно быть нашей первой идеей, как получить код.


Я попробовал этот код:

from dataclasses import dataclass
import inspect
import os
from uncompyle6 import PYTHON_VERSION, deparse_code2str

@dataclass
class C:
    name: str
    value: int = 34

inspect.getmembers(C) #('__init__', <function __init__(self, name: str, value: int = 34) -> None>)

co= C.__init__.__code__ # let's find out code for the __init__ method from code object

code = deparse_code2str(
                code=co,
                version=PYTHON_VERSION,
                out=open(os.devnull, "w"))
print(code)

Распечатает

self.name = name
self.value = value

Код использует Инспектор для понимания класса, а затем для декомпиляции методов с использованием декомпилятора Python.

Вот обнаруженные методы:

def __eq__(self, other):
    if other.__class__ is self.__class__:
        return (self.name, self.value) == (
            other.name,
            other.value,
        )
    else:
        return NotImplemented

def __init__(self, name: str, value: int = 34) -> None:
    self.name = name
    self.value = value

def __repr__(self):
    key = (id(self), _thread.get_ident())
    if key in repr_running:
        return "..."
    else:
        repr_running.add(key)
        try:
            result = user_function(self)
        finally:
            repr_running.discard(key)

        return result

На самом деле существует проект , который выполняет @dataclass discovery. Я установил его, и он работал.

from dataclasses import dataclass
import inspect
import os
import dis
from DataclassInspector.inspector import Inspector

@dataclass
class C:
    name: str
    value: int = 34

inspected = Inspector(C)
print(inspected._generate_code())

При условии вывода, как это:

from dataclasses import Field, _MISSING_TYPE, _DataclassParams
class C:
    __dataclass_fields__ = {'name': "Field(name='name', type=str, default=_MISSING_TYPE, default_factory=_MISSING_TYPE, init=True, repr=True, hash=None, compare=True, metadata={}, _field_type=_FIELD)", 'value': "Field(name='value', type=int, default=34, default_factory=_MISSING_TYPE, init=True, repr=True, hash=None, compare=True, metadata={}, _field_type=_FIELD)"}
    __dataclass_params__ = _DataclassParams(init=True,repr=True,eq=True,order=False,unsafe_hash=False,frozen=False)
    name: str
    value: int = 34

    def __eq__(self, other):
        if other.__class__ is self.__class__:
            return (self.name, self.value) == (other.name, other.value)
        else:
            return NotImplemented


    __hash__ = None

    def __init__(self, name: str, value: int = 34) -> None:
        self.name = name
        self.value = value



    def __repr__(self):
        key = (
         id(self), _thread.get_ident())
        if key in repr_running:
            return '...'
        else:
            repr_running.add(key)
            try:
                result = user_function(self)
            finally:
                repr_running.discard(key)

            return result
...