Получение имени экземпляра внутри класса __init __ () [duplicate]

На этот вопрос уже есть ответ здесь:

Получение имени переменной в виде строки 15 ответов

При создании нового объекта класса в python я хочу иметь возможность создавать значение по умолчанию на основе имени экземпляра класса без передачи дополнительного аргумента. Как я могу сделать это? Вот's основной псевдокод I 'я пытаюсь:

class SomeObject():
    defined_name = u""

    def __init__(self, def_name=None):
        if def_name == None:
            def_name = u"%s" % ()
        self.defined_name = def_name

ThisObject = SomeObject()
print ThisObject.defined_name   # Should print "ThisObject"
 SilentGhost06 нояб. 2009 г., 22:13
Зачем тебе это нужно?
 S.Lott06 нояб. 2009 г., 22:36
Тот'странно. Какой язык допускает такую ссылку на переменную времени компиляции во время выполнения?
 Akoi Meexx06 нояб. 2009 г., 22:18
Управление информацией о канале в сценарии irc для моей внутренней сети.

Ответы на вопрос(10)

имя может быть связано с объектом, после чего это имя можно использовать для поиска этого объекта.

Не имеет значения для объекта, с какими именами, если таковые имеются, он может быть связан. Это может быть связано с десятками разных имен, или ни одного. Кроме того, Python не имеет "обратные ссылки " эта точка от объекта к имени.

Рассмотрим этот пример:

foo = 1
bar = foo
baz = foo

Теперь предположим, что у вас есть целочисленный объект со значением 1, и вы хотите работать в обратном направлении и найти его имя. Что бы вы напечатали? С этим объектом связаны три разных имени, и все они одинаково действительны.

print(bar is foo) # prints True
print(baz is foo) # prints True

В Python имя - это способ доступа к объекту, поэтому нет возможности работать с именами напрямую. Вы можете искать в различных пространствах имен, пока не найдете имя, связанное с объектом интереса, но я нерекомендую это.

Как получить строковое представление переменной в Python?

Есть известная презентация под названием "Код как питониста " что обобщает эту ситуацию какДругие языки имеютПеременные» а также "Python имеетимена»

http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variablesI»

 Marcin06 окт. 2013 г., 19:54
@PythonLarry It 'верно, что некоторые языки имеют переменные математического типа; но это неэто означает, что языки, которые нет, неу меня нет переменных. "Переменная» это приемлемый термин для изменчивых переменных, несмотря на вашу неприязнь к нему.
 Marcin20 июн. 2013 г., 22:17
Прочитал презентацию. Я понимаю, это. Это'все еще неверно. В python указатель на объект копируется в переменную. Это также, почему Python является вызовом по значению. Еще раз, это не уникально для python.
 Marcin19 июн. 2013 г., 22:13
Извините, но в каком смысле у python нет переменных?
 Marcin20 июн. 2013 г., 13:37
(1) Вы не объясняете утверждение, что в питоне отсутствуют переменные. (2) Это неверно. Все языки, которые используют упакованные типы, имеют переменные, такие как python (за исключением того, что их переменные могут быть напечатаны). Это просто попытка заявить о различии для python, которого не существует.
 steveha20 июн. 2013 г., 22:13
@ Марчин, если вы действительно хотите понять мое первоначальное утверждение, прочитайте презентацию Бена Гуджера (слайд называется "Другие языки имеютПеременные» и следующий слайд называетсяPython имеетимена»). Затем рассмотрим выражениеa = b; на C-подобном языке это означаетзначение являетсяскопированный, но в Python это означаетназвание являетсяповторно связанный, Это различие, которое я пытался объяснить. Я прошу прощения, что вы нашли мое объяснение трудным для понимания.
 steveha20 июн. 2013 г., 07:20
@ Марчин, тебе было трудно понять мое объяснение? Я перепишу это немного, и, возможно, позже вы поймете это лучше.
 Marcin21 июн. 2013 г., 16:03
Это действительно неНеважно, как их называет языковой стандарт. Тот'Это хороший способ описания переменных, который позволяет избежать двусмысленности. Это незначит онине переменные. Мне действительно кажется, что вы и автор презентации не знакомы со многими языками программирования. Если бы вы были, вы бы не назвали это чем-то особенным.
 steveha21 июн. 2013 г., 08:05
@ Марчин, это будет мой последний комментарий в этой дискуссии. (Если мы продолжим идти вперед и назад, StackOverflow будет упрекать нас за то, что мы не переместили его на страницу обсуждения.) Если я правильно понимаю, ваша позиция заключается в том, что имена Python на самом деле должны рассматриваться как переменные, которым можно назначать ссылки только на объекты Python , Хотя это буквально верно, официальная документация для Python ссылается наимена» имея ценностиоценка» им и имена исключений следуют этой модели:docs.python.org/3/reference/executionmodel.html
 pythonlarry06 окт. 2013 г., 18:42
@ Марчин, возможноэто различие может помочь: В Python и некоторых других языкахlabel это просто имя поиска, и может быть уничтожено в любое время без необходимости уничтожения объекта, к которому он относится, или даже присвоения другому объекту без воздействия на первый объект, которому он был назначен.На некоторых других языкахпосле определенияvariable ЯВЛЯЕТСЯ объект, постоянно связанный с ним,и это имя не может быть повторно использовано.
 pythonlarry09 окт. 2013 г., 15:55
@Marcin,Я не "не нравится» семестрvariableЯ просто указывал на информацию, связанную с тем, что, по моему мнению, некоторые пытаются сказать: не то, что Python обязательнолучше ниуникальныйпросто что есть потенциалПопался если посмотреть наlabels с неправильной точки зрения - этоэтикетка,ссылкане объект. Тамявляются к сожалению, некоторые питонские сторонники, которые насмехаются надменьшее» языки, но я считаю, что большинство просто пытаются помочь другим знать различияпоэтому они не укушены неправильными предположениями.

я создал более сложный класс, который можно даже разделить на подклассы. Это решает то, что просили в вопросе ".

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

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

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

Код:

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()
</module>

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

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
Решение Вопроса

ThisObject получаетсвязанный к экземпляру, созданному путем оценкиSomeObject конструктор, конструктор завершил работу.

Если вы хотите, чтобы объект имел имя, просто передайте имя в конструкторе.

def __init__(self, name):
    self.name = name
 Jonathan Feinberg06 нояб. 2009 г., 22:33
Там нет такого понятия, как "переменная» по вашему определению. На каком языке какой-либо объект может быть связан только с одним именем?
 neuronet24 окт. 2017 г., 15:40
@JonathanFeinberg Я догадываюсь, что OP - уроженец Matlab. Такие вещи действительно просты в Matlab ... это ужасно для (компьютерной) памяти, легко для программиста.
 Akoi Meexx06 нояб. 2009 г., 22:31
Этот ответ понравился больше всего, так как яЯ уже знаю, что нетистинные переменные в Python (действительно должен быть способ получить имя, привязанное к экземпляру, но это 'это еще один аргумент для другого дня, я думаю). Это'логично, что это неимя не привязано к экземпляру, так что, думаю, покапросто потребуюdef_name» вместо 'def_name = None»
 Marcin19 июн. 2013 г., 22:12
@AkoiMeexx Серьезно, какой язык имеет "правда" переменные по вашему определению?

Ну, есть почти способ сделать это:

#!/usr/bin/env python
import traceback
class SomeObject():
    def __init__(self, def_name=None):
        if def_name == None:
            (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
            def_name = text[:text.find('=')].strip()
        self.defined_name = def_name

ThisObject = SomeObject()
print ThisObject.defined_name 
# ThisObject

Модуль traceback позволяет вам посмотреть код, используемый для вызова SomeObject (). С небольшим скручиванием строки,text[:text.find('=')].strip() Вы можете догадаться, каким должно быть def_name.

Однако этот хак хрупок. Например, это нетак хорошо работает:

ThisObject,ThatObject = SomeObject(),SomeObject()
print ThisObject.defined_name
# ThisObject,ThatObject
print ThatObject.defined_name 
# ThisObject,ThatObject

Так что, если вы собираетесь использовать этот хак, вы должны иметь в виду, что вы должны вызвать SomeObject () с помощью простого выражения python:

ThisObject = SomeObject()

Кстати, в качестве дальнейшего примера использования traceback, если вы определите

def pv(var):
    # stack is a list of 4-tuples: (filename, line number, function name, text)
    # see http://docs.python.org/library/traceback.html#module-traceback
    #
    (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
    # ('x_traceback.py', 18, 'f', 'print_var(y)')
    print('%s: %s'%(text[text.find('(')+1:-1],var))

тогда вы можете позвонить

x=3.14
pv(x)
# x: 3.14

распечатать имя переменной и ее значение.

 shylent06 нояб. 2009 г., 22:58
Вау, это так круто, что почти кричит "Вы не должны этого делать! :)
 unutbu06 нояб. 2009 г., 23:12
Сначала этоназывается хаком, потом окольным ... довольно скоробуду называть идиомой :)

как в выбранном ответе. Однако если выДЕЙСТВИТЕЛЬНО Чтобы не просить пользователя передать имя конструктору, вы можете сделать следующеевзломать:

Если вы создаете экземпляр с помощью 'ThisObject = SomeObject () ' из командной строки вы можете получить имя объекта из командной строки в истории команд:

import readline
import re

class SomeObject():
    def __init__(self):
        cmd = readline.get_history_item(readline.get_current_history_length())                                                          
        self.name = re.split('=| ',cmd)[0]

Если вы создаете экземпляр с помощью 'Exec» команда, вы можете справиться с этим:

if cmd[0:4] == 'exec': self.name = re.split('\'|=| ',cmd)[1]     # if command performed using 'exec'
else: self.name = re.split('=| ',cmd)[0]

что имена имеют значение, если они являются указателями на какой-либо объект .. не имеет значения, если:

foo = 1
bar = foo

Я знаю, что foo указывает на 1, а bar указывает на одно и то же значение 1 в том же пространстве памяти. но предположим, что я хочу создать класс с функцией, которая добавляет объект к нему.

Class Bag(object):
   def __init__(self):
       some code here...
   def addItem(self,item):
       self.__dict__[somewaytogetItemName] = item

Итак, когда я создаю экземпляр класса сумка, как показано ниже:

newObj1 = Bag()
newObj2 = Bag()
newObj1.addItem(newObj2)I can do this to get an attribute of newObj1:
newObj1.newObj2

который проверяет все переменные в текущем кадре и используетhash() искатьself переменная.

Предлагаемое здесь решение вернет все переменные, указывающие на объект экземпляра.

В классе ниже,isinstance() используется, чтобы избежать проблем при примененииhash(), так как некоторые объекты, такие какnumpy.array илиlist, например, небрежны.

import inspect
class A(object):
    def get_my_name(self):
        ans = []
        frame = inspect.currentframe().f_back
        tmp = dict(frame.f_globals.items() + frame.f_locals.items())
        for k, var in tmp.items():
            if isinstance(var, self.__class__):
                if hash(self) == hash(var):
                    ans.append(k)
        return ans

Следующий тест был сделан:

def test():
    a = A()
    b = a
    c = b
    print c.get_my_name()

Результат:

test()
#['a', 'c', 'b']

class SomeObject():
    def __init__(self, def_name):
        self.defined_name = def_name
        globals()[def_name] = self

SomeObject("ThisObject")
print ThisObject.defined_name

Если вы хотите поддержать что-то, кроме глобальной области, вы 'Я должен был сделать что-то еще более ужасное.

a = b = TheMagicObjet(), Имена не влияют на ценности, они просто указывают на них.

 u0b34a0f6ae07 нояб. 2009 г., 01:58
Как называются объекты в этом списке:L = [TheMagicObjet() for x in xrange(10)]
 Akoi Meexx06 нояб. 2009 г., 22:35
Да, но дело в том, что я неНе нужно сами значения, но имя указывает на них в виде строки.
 PaulMcG06 нояб. 2009 г., 23:04
В том то и дело, что в THC4k 'Например, TheMagicObjet () имеет 2 имени, указывающих на него, 'a' и "б" - какой вы хотите?

попробуйте__repr__() или жеid(self)

class Some:
    def __init__(self):
        print(self.__repr__())  # = hex(id(self))
        print(id(self))

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

Ваш ответ на вопрос