2009-06-29 23 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 2009-06-29 13:14:23

+0

是的,我可以通過調整ctypeslib的代碼來控制它。 – 2009-06-29 15:49:07

回答

7

我不認爲你想要什麼是直接可能的Python。

但是,您可以嘗試以下方法之一。

  1. 當生成to_import_from.py時,也在那裏添加非生成的東西。這樣, 所有的方法都在相同的類定義中。
  2. 已有to_import_from.py包含儀器類 繼承的基類定義。

換句話說,在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看起來只是我需要的解決方案。非常感謝! – 2009-06-29 15:51:50

3

我很遺憾,這是怎樣的一個"You shouldn't be putting nails in the wall" answer的,但是你錯過了python類定義的一點。你應該把,而與它在其自己的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.使用機器生成的代碼擴展基類。然後import machine_generated

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... 

您的應用程序可以使用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

從技術上講,是的,這是可能的,但這樣解決它並不是真正的慣用python,並有可能更好的解決方案。這裏有一個如何做這樣一個例子:

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)