Есть ли модуль Python для обработки адресов объектов Python?

StackOverflow https://stackoverflow.com/questions/3684151

Вопрос

(Когда я говорю «адрес объекта», я имею в виду строку, которую вы вводите в Python, чтобы получить доступ к объекту. Например 'life.State.step'. Отказ В большинстве случаев все объекты перед последней точкой будут пакеты / модули, но в некоторых случаях они могут быть классами или другими объектами.)

В моем Python Project Я часто имею необходимость играть с адресами объектов. Некоторые задачи, которые я должен сделать:

  1. Учитывая объект, получите его адрес.
  2. Учитывая адрес, получите объект, импортируя любые необходимые модули на пути.
  3. Укоротить адрес объекта путем избавления от резервных промежуточных модулей. (Например, 'life.life.State.step' может быть официальный адрес объекта, но если 'life.State.step' Очки в том же объекте, я бы хотел использовать его вместо этого, потому что он короче.)
  4. Укоротить адрес объекта путем «укоренения» указанного модуля. (Например, 'garlicsim_lib.simpacks.prisoner.prisoner.State.step' может быть официальный адрес объекта, но я предполагаю, что пользователь знает, где prisoner пакет, поэтому я хотел бы использовать 'prisoner.prisoner.State.step' как адрес.)

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

Одно примечание: Пожалуйста, не пытайтесь показать мне быструю реализацию этих вещей. Это сложнее, чем похоже, есть много gotchas, и любой Quick-N-грязный код, вероятно, не будет терпеть неудачу для многих важных случаев. Подобные задачи звонят для тестированного битва кода.

ОБНОВИТЬ: Когда я говорю «объект», я в основном имею в виду классы, модули, функции, методы, такие вещи. Извините за то, что не сделал это ясно раньше.

Это было полезно?

Решение 2

Я выпустил address_tools Модуль, который имеет именно то, о чем я просил.

Вот код. Вот тесты.

Это часть Гарницим, так что вы можете использовать его Установка garlicsim и делать from garlicsim.general_misc import address_tools. Отказ Его основные функции describe а также resolve, которые параллельны repr а также eval. Отказ Docstrings объясняет все о том, как работают эти функции.

Есть даже версия Python 3 на Python 3 вилка Garlicsim. Отказ Установите его, если вы хотите использовать address_tools на Python 3 кода.

Другие советы

Краткий ответ: Нет. То, что вы хотите, невозможно.

Долгий ответ - это то, что вы думаете о том, как «адрес» объекта, это что-то, кроме. life.State.step просто один из способов получить ссылку на объект в этом конкретном времени. Отказ Тот же «адрес» на более поздней точке может дать вам другой объект, или это может быть ошибка. Более того, этот «адрес» вашего зависит от контекста. Отказ В life.State.step, конечный объект зависит не только на том, что life.State а также life.State.step есть, но Какой объект имени life относится к тому пространству имен.

Конкретные ответы на ваши запросы:

  1. Конечный объект имеет никто ничего Выяснение того, как вы ссылаетесь на него, и не имеет ни одного кода, который вы даете объекту. «Адрес» не является именем, он не привязан к объекту, это просто произвольное выражение Python, которое приводит к ссылке на объект (как делают все выражения.) Вы можете только сделать эту работу, едва, С определенными объектами, которые не ожидают перемещения, такие как классы и модули. Даже так, эти объекты могу двигаться вокруг и часто делать Передвигаться вокруг, так что вы пытаетесь, скорее всего, сломается.

  2. Как уже упоминалось, «адрес» зависит от многих вещей, но эта часть довольно проста: __import__() а также getattr() может дать вам эти вещи. Однако они будут чрезвычайно хрупкими, особенно когда есть все больше, чем просто доступ атрибута. Это может только удаленно работать с вещами, которые находятся в модулях.

  3. «Укорочение» имя требует изучения все возможное имя, означает все модули и все локальные имена, а также все атрибуты их, регласно. Это было бы очень медленным и трудоемким процессом, и чрезвычайно хрупкий перед лицом чего-либо с __getattr__ или __getattribute__ Способ или со свойствами, которые делают больше, чем возвращает значение.

  4. то же самое 3.

Для точек 3 и 4, я думаю, что вы ищете, как

from life import life  # life represents life.life
from garlicsim_lib.simpacks import prisoner

Тем не менее, это не рекомендуется, так как это делает его сложнее или людям, которые читают ваш код, чтобы быстро узнать, что prisoner Представляет (где это приходит модуль? Вы должны посмотреть на начало кода, чтобы получить эту информацию).

Для пункта 1 вы можете сделать:

from uncertainties import UFloat

print UFloat.__module__  # prints 'uncertainties'

import sys
module_of_UFloat = sys.modules[UFloat.__module__]

Для точки 2, учитывая строку 'Garlicsim_lib.simpacks.prisoner', вы можете получить объект, который он относится к:

obj = eval('garlicsim_lib.simpacks.prisoner')

Это предполагает, что вы импортировали модуль с

import garlicsim_lib  # or garlicsim_lib.simpacks

Если вы даже хотите, чтобы это было автоматическим, вы можете сделать что-то вдоль линий

import imp

module_name = address_string.split('.', 1)[0]
mod_info = imp.find_module(module_name)
try:
    imp.load_module(module_name, *mod_info)
finally:
    # Proper closing of the module file:
    if mod_info[0] is not None:
        mod_info[0].close()

Это работает только в простейших случаях (garlicsim_lib.simpacks нужно быть доступно в garlicsim_lib, например).

Кодирование вещей таким образом, однако, очень необычно.

Виритый имеет # 2, как скрученный / Python / Refrect.py. Вам нужно что-то подобное для создания строковой системы конфигурации, например, с помощью конфигурации URLS. Django.

Посмотрите на код и журнал управления версией, чтобы увидеть, что им пришлось сделать, чтобы сделать его работать - и потерпеть неудачу! - правильный путь.

Другие вещи, которые вы ищете достаточно ограничения на окружающую среду Python, что нет такой вещи, как решение общего назначения.

Вот что-то, что несколько реализует ваш # 1

>>> import pickle
>>> def identify(f):
...   name = f.__name__
...   module_name = pickle.whichmodule(f, name)
...   return module_name + "." + name
... 
>>> identify(math.cos)
'math.cos'
>>> from xml.sax.saxutils import handler
>>> identify(handler)
'__main__.xml.sax.handler'
>>> 

Ваше № 3 недоомеется. Если я сделаю

__builtin__.step = path.to.your.stap

Тогда должен ли код поиска найти его как «шаг»?

Самая простая реализация, которую я могу придумать просто поискать все модули и ищет элементы верхнего уровня, которые именно вы хотите

>>> import sys
>>> def _find_paths(x):
...   for module_name, module in sys.modules.items():
...     if module is None:
...         continue
...     for (member_name, obj) in module.__dict__.items():
...       if obj is x:
...         yield module_name + "." + member_name
... 
>>> def find_shortest_name_to_object(x):
...   return min( (len(name), name) for name in _find_paths(x) )[1]
... 
>>> find_shortest_name_to_object(handler)
'__builtin__._'
>>> 5
5
>>> find_shortest_name_to_object(handler)
'xml.sax.handler'
>>> 

Здесь вы можете увидеть, что «обработчик» на самом деле был в _ от предыдущего возврата выражения, что делает его кратчайшим именем.

Если вы хотите что-то еще, вроде рекурсивно ищете всех членов всех модулей, а затем просто код. Но как пример «_» показывает, будут сюрпризы. Кроме того, это не стабильно, поскольку импорт другого модуля может сделать еще один путь объекта доступен и короче.

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

И как для вашего # 4, как в мире будет любая общая посылка для тех нуждающихся на именах?

В любом случае вы написали

Пожалуйста, не пытайтесь показать мне быструю реализацию этих вещей. Это сложнее, чем похоже, есть много gotchas, и любой Quick-N-грязный код, вероятно, не будет терпеть неудачу для многих важных случаев. Подобные задачи звонят для тестированного битва кода.

Так что не думайте о моих примерах как решения, но в качестве примеров того, что вы просите, имеет немного смысла. Это такое пространство хрупкого решения, что немногие, которые там рискуют (в основном для любопытства) имеют такие разные проблемы, что одностороннее индивидуальное решение - лучшее. Модуль для большинства из них не имеет смысла, и если оно имеет смысл объяснения того, что модуль, вероятно, будет длиннее кода.

И, следовательно, ответ на ваш вопрос: «Нет, таких модулей нет».

Что делает ваш вопрос еще более запутанным состоит в том, что реализация C Python уже определяет «адрес объекта». То Документы для ID () сказать:

Деталь внедрения Cpython: это адрес объекта.

То, что вы ищете, это имя, или путь к объекту. Не «адрес объекта Python».

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top