Python: использовать импорт внутри класса в функции - PullRequest
3 голосов
/ 30 июля 2011

Может кто-нибудь объяснить, как заставить работать следующий пример?Поскольку несколько функций внутри класса будут использовать одну и ту же функцию с платформы, я подумал, что было бы лучше импортировать ее прямо в класс, но я не понимаю, как я могу использовать ее внутри функции (поскольку я постоянно получаю ошибкиоб этом).

#!/usr/bin/python

class test:
   from platform import system
   is_linux(self):
      system = system()
      if system == "Linux": return True

Лучший пример:

#!/usr/bin/python

# Add ANSI colour strings
class stdout:
    from sys import stdout
    def message(message, self):  stdout.write(message)

Примечание: это просто фрагмент, некоторые части отсутствуют, но пример того, что я имею в виду.Я знаю, что мог бы просто переместиться system = system() и использовать self.system, но, возможно, лучше?

Ответы [ 4 ]

8 голосов
/ 30 июля 2011

Ну, это не так просто. На самом деле, оператор import во многих отношениях выглядит как прямое определение чего-то вместо этого. Если вы напишите

class test:
    from platform import system

это выглядит так же, как

class test:
    def system():
        # ....

и тогда у вас возникают следующие проблемы:

  1. вы не можете использовать только system (), потому что система не находится в глобальной области видимости
  2. вы не можете использовать self.system (), потому что в этой форме python автоматически передает self в качестве первого аргумента, но system () не имеет параметров, и вы получите TypeError: system() takes no arguments (1 given)
  3. вы не можете использовать test.system (), потому что system () выглядит как простой метод, и вы получите TypeError: unbound method system() must be called with test instance as first argument (got nothing instead)

Существует несколько способов решения этих проблем:

  1. поместите import platform на верхний уровень и используйте platform.system (), где вы хотите, тем самым устраняя проблему № 1 из пред. список
  2. используйте staticmethod decorator, исправляя проблемы № 2 и № 3 из пред. список.

как

class test:
    from platform import system
    system = staticmethod(system)

тогда вы можете использовать либо self.system (), либо test.system ()

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

import foo
import bar

def fun(param1, param2):
    # .....

if __name__ == '__main__':
    from sys import argv
    if len(argv) > 2:
        fun(argv[1], argv[2])

В этом примере перемещение from sys import argv допустимо, поскольку оно необходимо только при запуске скрипта. Но когда вы используете его как импортированный модуль, в этом импорте нет необходимости. Но это не ваш случай, потому что в вашем случае system () всегда необходим для тестового класса, поэтому нет причин переносить этот импорт с верхнего уровня. Просто оставь это там и не обращай внимания.

2 голосов
/ 28 июля 2012

Я удивлен, что никто не подумал об этом:

class test:
    def __init__(self):
        from platform import system
        self.system = system()
    def test(self):
        return self.system()

d = test()
print d.system()
print d.test()
1 голос
/ 30 июля 2011

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

В качестве альтернативы, в зависимости от того, что кажетсявы пытаетесь это сделать, вы можете попытаться создать подклассы некоторых вещей, которые вы используете (что, радикально упрощенно, похоже на extends в Java.)

0 голосов
/ 30 июля 2011

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

...