Python: Как мне создать ссылку на ссылку? - PullRequest
1 голос
/ 17 мая 2010

Я традиционно программист на Perl и C ++, поэтому заранее прошу прощения, если я неправильно понял что-то тривиальное в Python!

Я хотел бы создать ссылку на ссылку. А? Хорошо. Все объекты в Python на самом деле являются ссылками на реальный объект. Итак, как мне создать ссылку на эту ссылку?

Зачем мне это нужно? Я переопределяю sys.stdout и sys.stderr для создания библиотеки журналов. Я хотел бы получить ссылку (второго уровня) на sys.stdout.

Если бы я мог создать ссылку на ссылку, то я мог бы создать общий класс регистратора, где функция init получает ссылку на ссылку на дескриптор файла, которая будет переопределена, например, sys.stdout sys.stderr. В настоящее время я должен жестко закодировать оба значения.

Cheers, Kevin

Ответы [ 5 ]

6 голосов
/ 17 мая 2010

Проще, чем сказано:

ostream = sys.stdout
print >> ostream, 'hi mom!'
ostream = sys.stderr
print >> ostream, 'hi mom!'
ostream = open('mylog.txt', 'a')
...

И посмотрите на стандартный модуль регистрации , когда под вашим поясом появится еще немного Python.

Этот ответ основывался на предположении, исходя из уровня вопроса, о том, что действительно было необходимо. Понятие ссылки на ссылку не требуется в Python, вы можете мультиплексировать через список или диктовку, если хотите:

outputs = [sys.stderr, my_open_file_object_which_is_really_a_reference]
print >> outputs[0], 'hi dad!'
outputs = {'terminal': sys.stderr, 'logfile': file_object}
print >> outputs['logfile'], 'goodbye world!'

и т. Д.

1 голос
/ 17 мая 2010

Как говорят другие ответы, в python нет настоящих "ссылок на ссылки", но есть способы получить почти такой же эффект:

>>> reference1 = "Some Data"
>>> reference2 = (reference1,)
>>> def f(data):
    print data

>>> f(reference2)
('Some Data',)
>>> f(*reference2)
Some Data
1 голос
/ 17 мая 2010

Вы не можете создавать ссылки на ссылки в python. Однако вы можете переопределить файлы stderr и stdout с помощью пользовательских классов с помощью методов write и т. Д., Чтобы разрешить собственные системы ведения журнала:

import sys

class MyLogger:
    def __init__(self, f):
        self.f = f

    def __getattr__(self, name):
        # forward e.g. flush() calls to the original file
        return getattr(self.f, name)

    def write(self, data):
        # log the data here!
        # ...

        # And write to the original file
        self.f.write(data)

sys.stdout = MyLogger(sys.stdout)
sys.stderr = MyLogger(sys.stderr)
0 голосов
/ 17 мая 2010

Во-первых, уже есть модуль logging , так что вам, вероятно, стоит использовать его. Во-вторых, хотя ссылки на ссылку не существует, вы можете добиться этого косвенного обращения с помощью оболочки или функции. Например, если вам нужно создать функцию получения и установки для назначения объекта, например:

 class StdOutWrapper(object):
      def __init__(self):
          self.original = sys.stdout

      @property
      def value(self):
          return sys.stdout

      @value.setter
      def value(self,val):
          sys.stdout = val

Затем вы можете передать экземпляр этого объекта вашему регистратору для назначения / разыменования sys.stdout.

0 голосов
/ 17 мая 2010

Этого нельзя сделать. Передайте нужный атрибут в виде строки и используйте getattr() и setattr().

...