присваивать имя переменной объекту при присвоении переменной

#python

#python

Вопрос:

В python переменная имеет имя, а объект — нет (поскольку несколько переменных могут указывать на один и тот же объект)

Но есть ли способ добавить / изменить name свойство объекта, когда оно присваивается переменной.

В идеале, что-то, что работало бы следующим образом:

 spam = MagicObject()
print(spam.name) # output: "spam"
ham = spam
print(spam.name) # output: "ham"
  

Редактировать: На самом деле, я действительно не возражаю, если вторая печать будет «ветчина» или «спам», поскольку я действительно не планирую, чтобы несколько переменных указывали на один и тот же объект. Я просто хочу, чтобы у объекта было имя независимо от сценария.

Моя идея состоит в том, чтобы создать какой-то файл параметров с как можно меньшим количеством записей. Чтобы этот простой код:

 person_id = PrimaryKey()
  

создал бы объект PrimaryKey и автоматически назвал бы его «person_id»

Комментарии:

1. Нет. spam практически невозможно узнать, что оно было присвоено чему-либо, не говоря уже об имени правопреемника

2. @PhxDev вообще не связан с тем, что пытается сделать OP

3. Кроме того, что, по-вашему, произойдет, если мы это сделаем a, b = spam, spam ?

4. Переменные являются просто заполнителями в алгоритме. Их конкретное имя не должно иметь значения, тем более что вы иногда ограничены в именах, которые вы можете использовать для данной переменной, и, следовательно, не можете присвоить ей какое-либо конкретное значение.

5. Это выполнимо с помощью атрибутов класса, например, class Foo: bar = Baz() , а затем большого количества метаклассов или __init__ магии… Но для автономных переменных это плохая идея.

Ответ №1:

Я думаю, что это максимально приближено к тому, что вы пытаетесь сделать. Это неэффективно и злоупотребляет globals и properties . Кроме того, если MagicObject это сложно, это нужно будет реализовать __eq__ (и, вероятно __hash__ , также хорошо).

Это взлом, и, вероятно, его не следует использовать в производстве.

  class MagicObject:
    @property
    def name(self):
        return [k for k, v in globals().items() if v == self]

a = MagicObject()
print(a.name)
b = a
print(a.name)
c = a
print(a.name)
del b
print(a.name)
  

Выводит

 ['a']
['a', 'b']
['a', 'b', 'c']
['a', 'c']
  

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

Комментарии:

1. Это, конечно, неэффективно, но я не вижу здесь злоупотреблений. Globals и property для меня это абсолютно верные инструменты. Вы можете сделать это произвольным списком с помощью return sorted([k for k, v in globals().items() if v == self]) . В любом случае, я действительно не планирую иметь несколько переменных для объекта. Я просто хотел уточнить, что объект может иметь уникальное (хотя и несколько произвольное) имя, что бы ни случилось.

2. Я думаю, вам следует заменить v==self на v is self . Нет необходимости переопределять __eq__ таким образом, и в любом случае это более логично

3. @Madlozoz Не обязательно, это полностью зависит от реализации MagicObject и того, чего вы пытаетесь достичь, как я объяснил в своем ответе. В случае, если __eq__ не определено, == в любом случае возвращается к is

Ответ №2:

Похоже, вы хотите написать ORM. Два предложения:

  • Не делайте этого. Используйте уже написанный, например, SQLAlchemy.
  • Если вы делаете что-то еще, или вы действительно хотите спуститься в эту кроличью нору, проверьте, как эти ORM делают это, скорее всего, с помощью метакласса.