2009-06-29 2 views
8

Интересно, если это возможно, чтобы сохранить методы класса Python в другой файл из определения класса, что-то вроде этого:методов Импортирующих для класса Python

main_module.py:

class Instrument(Object): 
    # Some import statement? 
    def __init__(self): 
     self.flag = True 
    def direct_method(self,arg1): 
     self.external_method(arg1, arg2) 

to_import_from.py:

def external_method(self, arg1, arg2): 
    if self.flag: 
     #doing something 
#...many more methods 

В моем случае to_import_from.py является машинным генератором и содержит множество методов. Я предпочел бы не скопировать и вставить их в main_module.py или импортировать их один за другим, но у них все признали в качестве методов класса инструментов, так же, как если бы они были определены здесь:

>>> instr = Instrument() 
>>> instr.direct_method(arg1) 
>>> instr.external_method(arg1, arg2) 

Спасибо!

+0

Вы управляете поколением to_import_from.py или вам нужно использовать его как «как есть»? – itsadok

+0

Да, я могу немного контролировать его, изменив код ctypeslib. –

ответ

7

Я не думаю, что вы можете прямо в Python.

Вы можете, однако, попробовать одно из следующих.

  1. При создании to_import_from.py добавьте туда не созданный материал. Таким образом, все методы находятся в одном определении класса.
  2. У to_import_from.py есть определение базового класса, которое наследует класс Instrument .

Другими словами, в to_import_from.py:

class InstrumentBase(object): 
    def external_method(self, arg1, arg2): 
     if self.flag: 
      ... 

, а затем в main_module.py:

import to_import_from 

class Instrument(to_import_from.InstrumentBase): 
    def __init__(self): 
     ... 
+2

Вариант 2 выглядит просто как раз то, что мне нужно. Большое спасибо! –

3

Мне очень жаль, что это своего рода "You shouldn't be putting nails in the wall" answer, но вы пропустили точка определения класса python. Вы должны скорее положить класс со всеми методами в своем собственном файле питон, и в вашем main_module.py сделать

from instrument import Instrument 

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

Наконец, дайте вашему классу хорошую докструю, которая объясняет API для пользователя, поэтому нет необходимости использовать «заголовочный файл», используемый в качестве обзора вашего класса.

4

вы можете сделать это с помощью метода __getattr__

external.py

def external_function(arg): 
    print("external", arg) 

main.py:

import external 

class Instrument(object): 
    def __getattr__(self, name): 
     if hasattr(external, name): 
      return getattr(external, name) 
     else: 
      return Object.__getattr__(self, name) 

    def direct_method(self, arg): 
     print("internal", arg) 


i = Instrument() 
i.direct_method("foo") 
i.external_function("foo") 
2

Что вы делаете расширяет базовый класс с некоторыми " машинный "код.

Выбор 1. Расширьте базовый класс с помощью машинного кода.

machine_generated.py

# Start of boilerplate # 
import main_module 
class Instrument_Implementation(main_module.Instrument_Abstraction): 
    def direct_method(self,arg1): 
     # End of boilerplate # 
     ...the real code... 

Ваше приложение может import machine_generated и использовать machine_generated.Instrument_Implementation.

Выбор 2. Просто используйте первоклассные функции.

machine_generated.py

def external_method(self, arg1, arg2): 
    ...the real code... 

main_module.py

import machine_generated 

class Instrument(object): 
    def direct_method(self,arg1): 
     return machine_generator.external_method(arg1, ...) 

Ваше приложение может import main_module и использовать main_module.Instrument.

6

Это проще, чем вы думаете:

class Instrument(Object): 
    def __init__(self): 
     self.flag = True 
    def direct_method(self,arg1): 
     self.external_method(arg1, arg2) 

import to_import_from 

Instrument.external_method = to_import_from.external_method 

Готово!

Несмотря на то, что сгенерированный машиной код генерирует определение класса, и подклассы из него были бы более аккуратным решением.

0

Вот моя попытка. Я думаю, что лучше подход может быть сделано с метаклассами ...

to_import_from.py:

def external_method(self, arg1, arg2): 
    if self.flag: 
     print "flag is set" 
    else : 
     print "flag is not set" 

instrument.py:

import imp 
import os 
import inspect 
import new 

import pdb 

class MethodImporter(object) : 
    def __init__(self, path_to_module) : 
     self.load_module(path_to_module) 

    def load_module(self, path_to_module) : 
     name = os.path.basename(path_to_module) 
     module_file = file(path_to_module,"r") 
     self.module = imp.load_module(name, module_file , path_to_module, ('','r',imp.PY_SOURCE)) 
     print "Module %s imported" % self.module 
     for method_name, method_object in inspect.getmembers(self.module, inspect.isfunction) : 
      print "adding method %s to %s" % (method_name, self) 
      setattr(self, method_name, new.instancemethod(method_object, self, self.__class__)) 


class Instrument(MethodImporter): 
    def __init__(self): 
     super(Instrument,self).__init__("./to_import_from.py") 
     self.flag = True 
    def direct_method(self,arg1): 
     self.external_method(arg1, arg2) 

при запуске этого кода

arg1, arg2 = 1, 2 
instr = Instrument() 
instr.direct_method(arg1) 
instr.external_method(arg1, arg2) 

вот вывод:

Module <module 'to_import_from.py' from './to_import_from.pyc'> imported 
adding method external_method to <__main__.Instrument object at 0x2ddeb0> 
flag is set 
flag is set 
0

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

import to_import_from 

class Instrument(object): 
    locals().update(dict((k,v) for (k,v) in 
        to_import_from.__dict__.iteritems() if callable(v))) 

    def __init__(self): 
     self.flag = True 
    def direct_method(self,arg1): 
     self.external_method(arg1, arg2) 

Это будет импортировать все вызываемые функции, определенные в to_import_from в качестве методов Instrument класса, а также добавление еще несколько методов. Примечание: если вы также хотите скопировать глобальные переменные в качестве переменных экземпляра, вам нужно уточнить проверку. Также обратите внимание, что это добавляет все вызываемые объекты, которые он находит в пространстве имен to_import_from, в том числе импорт из других модулей (т.е. from module import some_func импорта стилей)

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

class Instrument(to_import_from.BaseClass): 
    # Add new methods here. 
7

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

class Instrument(Object): 
    # load external methods 
    from to_import_from import * 

    def __init__(self): 
     self.flag = True 
    def direct_method(self,arg1): 
     self.external_method(arg1, arg2) 
+1

Синтаксис Предупреждение: импорт * разрешен только на уровне модуля –

+2

+1 Даже если * неверно, это отличный, чистый отзыв. – thethinman

+1

Это должен быть ответ. – bgusach

Смежные вопросы