Справка - указатели на функции в 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) у меня будут функции diff для float, double и так далее.

В зависимости от указателей на функции будет вызвана указанная функция.

Я не знаю, хорошие у меня знания программирования или плохие, но мне нужна помощь.

В Python почти никогда не требуется специфичная для типа обработка. Кроме того, поскольку select_fun (aFunction) каждый раз одно и то же, неясно, какой смысл в get select_fun (aFunction) из словаря.

S.Lott 31.12.2008 14:24
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
1
26 390
5

Ответы 5

Не могли бы вы уточнить, что вы пытаетесь сделать? Вам не нужно делать ничего особенного, чтобы получить указатели на функции в 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

Ваш ответ уместен. Но в случае 3 в качестве параметра я передаю указатель на функцию, который вызывает определенную функцию внутри select_fun.

user46646 31.12.2008 09:00

@ rejinacm.myopenid.com: вы по-прежнему не используете "указатели". Вы просто используете функцию как объект. Нет указателя. Просто передайте функцию.

S.Lott 31.12.2008 14:21

Раньше я использовал эту стратегию. Мне это показалось более медленным при выполнении, вероятно, когда функция начала значение dict, которое оно недавно скопировало в память, вместо того, чтобы работать как указатель. Есть какие-нибудь комментарии по этому поводу?

Mychot sad 18.01.2013 20:23

Вы можете использовать type() встроенная функция для определения типа функции.

Скажем, если вы хотите проверить, содержит ли определенное имя строковые данные, вы можете сделать это:

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, поэтому могут быть некоторые ошибки, но вы должны уловить идею.


Обновлено: Согласно предложению @ Adam, существуют встроенные константы типов, которые можно проверять напрямую, поэтому лучшим подходом будет:

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)

А поскольку сам ключ сопоставим со значением функции type (), вы можете просто сделать это:

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

Что более элегантно :-) за исключением проверки ошибок.


Обновлено: И для поддержки ctypes после некоторой игры я обнаружил, что ctypes. [Type_name_here] фактически реализован как классы. Так что этот метод все еще работает, вам просто нужно использовать классы типа 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)

Хотя технически правильно, я бы сказал, что было бы лучше сравнивать константы types.FloatType, types.StringType и types.IntType в модуле типов.

Adam Rosenfield 31.12.2008 08:54

call_option = лямбда-аргумент: параметры [тип (аргумент)] (аргумент)

jfs 31.12.2008 09:16

для беззнакового или подписанного типа, что мне делать?

user46646 31.12.2008 10:42

Как вы получаете беззнаковый тип в Python?

recursive 31.12.2008 10:50

Я вызываю dll, написанную на VB. Я проверяю ее тип и затем конвертирую соответственно. В pyhton есть основные типы данных ctypes, которые имеют вышеуказанное. Я хочу знать, как двигаться дальше ...

user46646 31.12.2008 12:58

Может быть, вы хотите каждый раз вызывать один и тот же 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
>>> 

Просто пытаюсь понять исходный вопрос, заданный в терминах call_option ().

gimel 31.12.2008 10:55

Функции являются первоклассными объектами в Python, поэтому вы можете передавать их в качестве аргументов другим функциям, как и любой другой объект, такой как строка или целое число.

В Python нет типа с плавающей запятой одинарной точности. float Python соответствует double C.

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

Вот пара примеров кода использования универсальных функций:

Глядя на ваш пример, мне кажется, что это какая-то процедура 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)

и т.п.

Опять же, все это в предположении, что вы переводите с процедурного языка на Python; если это не так, то откажитесь от моего ответа :-)

Другие вопросы по теме