2008-12-31 19 views
3

我的节目的想法:帮助 - 在Python函数指针

我有一本字典:

options = { 'string' : select_fun(function pointer), 
'float' : select_fun(function pointer), 
'double' : select_fun(function pointer) 
} 

任何类型涉及单一功能select_fun(function pointer)被调用。 在select_fun(function pointer)里面,我会有float,double等的diff函数。

根据函数指针,指定的函数将被调用。

我不知道我的编程知识是好还是坏,还是需要帮助。

+0

你几乎从不需要Python中的特定于类型的处理。此外,由于select_fun(aFunction)每次都是相同的事情,因此不清楚从字典中获取select_fun(aFunction)的哪个点。 – 2008-12-31 11:24:06

回答

20

你能更具体地说明你想做什么吗?你不必做任何特别的事情函数指针在Python - 您可以通过周围的功能,如常规对象:

def plus_1(x): 
    return x + 1 

def minus_1(x): 
    return x - 1 

func_map = {'+' : plus_1, '-' : minus_1} 

func_map['+'](3) # returns plus_1(3) ==> 4 
func_map['-'](3) # returns minus_1(3) ==> 2 
+0

您的回答是恰当的。但在3作为参数的情况下,我传递了一个函数指针,它在select_fun中调用一个特定的函数。 – user46646 2008-12-31 06:00:56

+0

@ rejinacm.myopenid.com:你仍然不使用“指针”。您只是将该函数用作对象。没有指针。只需传递函数即可。 – 2008-12-31 11:21:17

+0

在过去我使用这种策略。在我看来,执行起来更慢,可能当func开始一个字典值时,它最近被复制到内存中,而不是作为指针工作。对此有何评论? – 2013-01-18 16:23:05

6

可以使用type() built-in function检测功能的类型。

说,如果你想检查是否有特定名称持有一个字符串数据,你可以这样做:

if type(this_is_string) == type('some random string'): 
    # this_is_string is indeed a string 
你的情况

所以,你可以做这样的:

options = { 'some string'  : string_function, 
      (float)(123.456) : float_function, 
      (int)(123)  : int_function 
      } 

def call_option(arg): 

    # loop through the dictionary 
    for (k, v) in options.iteritems(): 

     # if found matching type... 
     if type(k) == type(arg): 

      # call the matching function 
      func = option[k] 
      func(arg) 

然后你可以使用它像这样:

call_option('123')  # string_function gets called 
call_option(123.456)  # float_function gets called 
call_option(123)   # int_function gets called 

我附近没有一个Python解释器,我在Python没有计划太多所以可能有一些错误,但你应该明白。


编辑:按@亚当的建议,也有内置式常量,你可以对证直接,所以更好的做法是:

from types import * 

options = { types.StringType : string_function, 
      types.FloatType : float_function, 
      types.IntType  : int_function, 
      types.LongType : long_function 
      } 

def call_option(arg): 
    for (k, v) in options.iteritems(): 

     # check if arg is of type k 
     if type(arg) == k: 

      # call the matching function 
      func = options[k] 
      func(arg) 

而且,由于密钥本身与类型()函数的值相当,你可以这样做:

def call_option(arg): 
    func = options[type(arg)] 
    func(arg) 

哪个更优雅:-)保存一些错误检查。


编辑:而对于ctypes的支持,一些摆弄周围后,我发现ctypes的[type_name_here]实际上implented为类。所以这个方法仍然有效,你只需要使用ctypes.c_xxx类型的类。

options = { ctypes.c_long  : c_long_processor, 
      ctypes.c_ulong : c_unsigned_long_processor, 
      types.StringType : python_string_procssor 
      } 

call_option = lambda x: options[type(x)](x) 
3

也许你想每次都调用相同的select_fun(),使用不同的参数。如果这是你的意思,你需要一个不同的词典:

>>> options = {'string' : str, 'float' : float, 'double' : float } 
>>> options 
{'double': <type 'float'>, 'float': <type 'float'>, 'string': <type 'str'>} 
>>> def call_option(val, func): 
...  return func(val) 
... 
>>> call_option('555',options['float']) 
555.0 
>>> 
4

函数是Python中的第一类对象,因此你可以将它们作为参数传递给其他的功能,你会与任何其他对象,如字符串或一个整数。

Python中没有单精度浮点类型。 Python的float对应于C的double

def process(anobject): 
    if isinstance(anobject, basestring): 
     # anobject is a string 
     fun = process_string 
    elif isinstance(anobject, (float, int, long, complex)): 
     # anobject is a number 
     fun = process_number 
    else: 
     raise TypeError("expected string or number but received: '%s'" % (
      type(anobject),)) 
    return fun(anobject) 

functools.singledispatch,允许创建一个通用的功能:

from functools import singledispatch 
from numbers import Number 

@singledispatch 
def process(anobject): # default implementation 
    raise TypeError("'%s' type is not supported" % type(anobject)) 

@process.register(str) 
def _(anobject): 
    # handle strings here 
    return process_string(anobject) 

process.register(Number)(process_number) # use existing function for numbers 

在Python 2中,类似的功能,可作为pkgutil.simplegeneric()

这里有一对夫妇使用泛型函数的代码示例:

4

看着你的榜样,在我看来,一些C程序,直接转换到Python。

由于这个原因,我认为可能会有一些设计问题,因为通常在Python中,您并不关心对象的类型,而只关心可以发送给它的消息。

当然,这种方法有很多例外,但在这种情况下,我会尝试封装一些多态;例如。

class StringSomething(object): 
    data = None 
    def data_function(self): 
    string_function_pointer(self.data) 

class FloatSomething(object): 
    data = None 
    def data_function(self): 
    float_function_pointer(self.data) 

同样,这一切你是从一个程序语言翻译蟒的假设下;如果不是这样,那么放弃我的答案:-)