IntelliJ IDEA & ldquo; Создать проект автоматически & rdquo; беды

Вдохновленный ответами unutbu и Saullo Castro, я создал более сложный класс, который может быть даже подклассифицирован. Он решает, что было задано в вопросе.

"создать значение по умолчанию, основанное на имени экземпляра класса, не передавая дополнительный аргумент."

Вот что он делает, когда экземпляр этого класса или подкласса:

  1. Перейти в стек кадров до первого кадра, который не принадлежит методу текущего экземпляра.
  2. Осмотреть это кадр для получения атрибутов self.creation_(name/file/module/function/line/text).
  3. Выполните дополнительную проверку, действительно ли объект с именем self.creation_name был определен в пространстве имен locals () фрейма, чтобы сделать 100% уверенным, что найденное имя_создания является правильным или /// g2]

Код:

import traceback, threading, time

class InstanceCreationError(Exception):
    pass

class RememberInstanceCreationInfo:
    def __init__(self):
        for frame, line in traceback.walk_stack(None):
            varnames = frame.f_code.co_varnames
            if varnames is ():
                break
            if frame.f_locals[varnames[0]] not in (self, self.__class__):
                break
                # if the frame is inside a method of this instance,
                # the first argument usually contains either the instance or
                #  its class
                # we want to find the first frame, where this is not the case
        else:
            raise InstanceCreationError("No suitable outer frame found.")
        self._outer_frame = frame
        self.creation_module = frame.f_globals["__name__"]
        self.creation_file, self.creation_line, self.creation_function, \
            self.creation_text = \
            traceback.extract_stack(frame, 1)[0]
        self.creation_name = self.creation_text.split("=")[0].strip()
        super().__init__()
        threading.Thread(target=self._check_existence_after_creation).start()

    def _check_existence_after_creation(self):
        while self._outer_frame.f_lineno == self.creation_line:
            time.sleep(0.01)
        # this is executed as soon as the line number changes
        # now we can be sure the instance was actually created
        error = InstanceCreationError(
                "\nCreation name not found in creation frame.\ncreation_file: "
                "%s \ncreation_line: %s \ncreation_text: %s\ncreation_name ("
                "might be wrong): %s" % (
                    self.creation_file, self.creation_line, self.creation_text,
                    self.creation_name))
        nameparts = self.creation_name.split(".")
        try:
            var = self._outer_frame.f_locals[nameparts[0]]
        except KeyError:
            raise error
        finally:
            del self._outer_frame
        # make sure we have no permament inter frame reference
        # which could hinder garbage collection
        try:
            for name in nameparts[1:]: var = getattr(var, name)
        except AttributeError:
            raise error
        if var is not self: raise error

    def __repr__(self):
        return super().__repr__()[
               :-1] + " with creation_name '%s'>" % self.creation_name

Простой пример:

class MySubclass(RememberInstanceCreationInfo):
    def __init__(self):
        super().__init__()

    def print_creation_info(self):
        print(self.creation_name, self.creation_module, self.creation_function,
                self.creation_line, self.creation_text, sep=", ")

instance = MySubclass()
#out: instance, __main__, <module>, 68, instance = MySubclass()

Если имя создания не может быть определено правильно возникает ошибка:

variable, another_instance = 2, MySubclass()

# InstanceCreationError: 
# Creation name not found in creation frame.
# creation_file: /.../myfile.py 
# creation_line: 71 
# creation_text: variable, another_instance = 2, MySubclass()
# creation_name (might be wrong): variable, another_instance
17
задан informatik01 18 June 2019 в 12:22
поделиться