Как я могу вернуть имя, связанное с экземпляром объекта? [Дубликат]

Существует простой трюк Java для решения вашей проблемы. Вы должны указать экземпляр Class.forName(). Например:

 val customers: RDD[(Int, String)] = new JdbcRDD(sc, () => {
       Class.forName("com.mysql.jdbc.Driver")
       DriverManager.getConnection(jdbcUrl)
      },
      "SELECT id, name from customer WHERE ? < id and id <= ?" ,
      0, range, partitions, r => (r.getInt(1), r.getString(2)))

Проверьте документы

16
задан Jonathan Feinberg 6 November 2009 в 22:03
поделиться

10 ответов

У экземпляров нет имен. К тому моменту, когда глобальное имя ThisObject привязано к экземпляру, созданному при оценке конструктора SomeObject, конструктор закончил работу.

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

def __init__(self, name):
    self.name = name
20
ответ дан Jonathan Feinberg 24 August 2018 в 18:07
поделиться
  • 1
    Понравился этот ответ лучше всего, так как я уже знаю, что в Python нет истинных переменных (на самом деле все равно должен быть способ захватить имя, привязанное к экземпляру, но это еще один аргумент для другого дня, который я предполагаю). Логично, что у него не было бы имени, связанного с экземпляром, поэтому я предполагаю, что на данный момент я просто требую «def_name» вместо «def_name = None», – Akoi Meexx 6 November 2009 в 22:31
  • 2
    Нет такой вещи, как «переменная». по вашему определению. На каком языке может быть привязан какой-то объект к одному имени? – Jonathan Feinberg 6 November 2009 в 22:33
  • 3
    @AkoiMeexx Серьезно, какой язык имеет «истина»? переменные по вашему определению? – Marcin 19 June 2013 в 21:12
  • 4
    @JonathanFeinberg Моя догадка - это OP, родной Matlab. В Matlab такая вещь очень проста ... это ужасно на (компьютерной) памяти, просто на программиста. – neuronet 24 October 2017 в 13:40

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

foo = 1
bar = foo

Я знаю, что foo указывает на 1 и штрих указывает на одно и то же значение 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
0
ответ дан andrexterz 24 August 2018 в 18:07
поделиться

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

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

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

foo = 1
bar = foo
baz = foo

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

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

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

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

Существует известная презентация под названием «Code Like a Pythonista», которая суммирует эту ситуацию как «Другие языки имеют« переменные »и« у Python есть имена »

http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html# другие языки-чтобы-переменные

2
ответ дан Community 24 August 2018 в 18:07
поделиться
  • 1
    Извините, но в каком смысле у python нет переменных? – Marcin 19 June 2013 в 21:13
  • 2
    @Marcin, вы нашли мое объяснение трудно понять? Я немного переписал его, и, возможно, вы поймете это позже. – steveha 20 June 2013 в 06:20
  • 3
    (1) Вы не объясняете утверждение, что на python отсутствуют переменные. (2) Это неверно. Все языки, использующие типы в штучной упаковке, имеют такие переменные, как python (за исключением того, что их переменные могут быть напечатаны). Это просто попытка заявить о различии для python, которого нет. – Marcin 20 June 2013 в 12:37
  • 4
    @Marcin, если вы действительно хотите понять мое первоначальное заявление, пожалуйста, прочитайте презентацию Бен Гудгера (слайд под названием «Другие языки имеют« переменные »и« следующий слайд »под названием« Python имеет имена »и«). Затем рассмотрим выражение a = b; на C-подобном языке это означает, что значение скопировано , но в Python это означает, что name is re-bound < / я>. Это различие, которое я пытался объяснить. Прошу прощения, что вы нашли мое объяснение трудным для понимания. – steveha 20 June 2013 в 21:13
  • 5
    Я прочитал презентацию. Я понимаю. Это все еще неправильно. В python указатель на объект копируется в переменную. Это также почему python - это вызов по значению. Еще раз, это не уникально для python. – Marcin 20 June 2013 в 21:17

Лучший способ - это передать имя конструктору, как в выбранном ответе. Однако, если вы действительно НЕ хотите, чтобы пользователь не передавал имя конструктору, вы можете выполнить следующий взлом:

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

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]
-1
ответ дан computerist 24 August 2018 в 18:07
поделиться

Если вы хотите уникальное имя экземпляра для класса, попробуйте __repr__() или id(self)

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

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

0
ответ дан Guillaume Lebreton 24 August 2018 в 18:07
поделиться

Это не сработает, просто представьте это: a = b = TheMagicObjet(). Имена не влияют на значения, они просто указывают на них.

3
ответ дан Jochen Ritzel 24 August 2018 в 18:07
поделиться
  • 1
    Правильно, но факт в том, что я не хочу самих значений, но имя указывает на них как на строку. – Akoi Meexx 6 November 2009 в 22:35
  • 2
    Дело в том, что в примере THC4k TheMagicObjet () имеет 2 имени, указывающих на него: «a» и «b» - какой вы хотите? – PaulMcG 6 November 2009 в 23:04
  • 3
    Каковы имена объектов в этом списке: L = [TheMagicObjet() for x in xrange(10)]? – u0b34a0f6ae 7 November 2009 в 01:58

Один ужасный, ужасный способ добиться этого - отменить обязанности:

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

SomeObject("ThisObject")
print ThisObject.defined_name

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

2
ответ дан Russell Borogove 24 August 2018 в 18:07
поделиться

Вы можете создать метод внутри вашего класса, который проверяет все переменные в текущем фрейме и использует 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']
6
ответ дан Saullo G. P. Castro 24 August 2018 в 18:07
поделиться

Вдохновленный ответами 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
0
ответ дан TheoRet 24 August 2018 в 18:07
поделиться

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

#!/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

Модуль трассировки позволяет вам заглянуть в код, используемый для вызова 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

, чтобы напечатать оба имя переменной и ее значение.

20
ответ дан unutbu 24 August 2018 в 18:07
поделиться
  • 1
    Woah, это так круто, он почти кричит «Вы не должны это делать!». :) – shylent 6 November 2009 в 22:58
  • 2
    Сначала это называется хак, потом круглая, ... довольно скоро его назовут идиомой :) – unutbu 6 November 2009 в 23:12
Другие вопросы по тегам:

Похожие вопросы: