Установить сигнатуру функции в Python

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

26
задан 15 revs, 2 users 98% 23 May 2017 в 12:02
поделиться

5 ответов

Для вашего варианта использования наличие строки документации в классе / функции должно работать - это будет отображаться в help () нормально, и может быть установлен программно (func .__ doc__ = "stuff").

Я не вижу никакого способа установить фактическую подпись. Я бы подумал, что модуль functools сделал бы это, если бы это было выполнимо, но это не так, по крайней мере, в py2.5 и py2.6.

Вы также можете вызвать исключение TypeError, если вы получаете неверный ввод.

Хм, если вы не против быть по-настоящему мерзким, вы можете использовать для этого compile () / eval (). Если ваша желаемая подпись указана arglist = ["foo", "bar", "baz"], а ваша фактическая функция - f (* args, ** kwargs), вы можете управлять:

argstr = ", ".join(arglist)
fakefunc = "def func(%s):\n    return real_func(%s)\n" % (argstr, argstr)
fakefunc_code = compile(fakefunc, "fakesource", "exec")
fakeglobals = {}
eval(fakefunc_code, {"real_func": f}, fakeglobals)
f_with_good_sig = fakeglobals["func"]

help(f)               # f(*args, **kwargs)
help(f_with_good_sig) # func(foo, bar, baz)

Изменение docstring и func_name должно дать вам полное решение. Но, эээ ...

15
ответ дан 28 November 2019 в 05:30
поделиться

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

# define a function
def my_func(name, age) :
    print "I am %s and I am %s" % (name, age)

# label the function with a backup name
save_func = my_func

# rewrite the function with a different signature
def my_func(age, name) :
    # use the backup name to use the old function and keep the old behavior
    save_func(name, age)

# you can use the new signature
my_func(35, "Bob")

Это выведет:

I am Bob and I am 35
0
ответ дан 28 November 2019 в 05:30
поделиться

Мы хотим, чтобы create_initiation_function изменила подпись

Пожалуйста, не делайте этого.

Мы хотим использовать эту функцию в нескольких классах

Пожалуйста, используйте обычное наследование.

Нет смысла "изменять" подпись во время выполнения.

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

Сделайте это вместо этого. Это просто и очевидно, и делает ваш общий init доступным во всех подклассах очевидным и простым способом Pythonic.

class Super( object ):
    def __init__( self, *args, **kwargs ):
        # the generic __init__ that we want every subclass to use

class SomeSubClass( Super ):
    def __init__( self, this, that, **kwdefaults ):
        super( SomeSubClass, self ).__init__( this, that, **kwdefaults )

class AnotherSubClass( Super ):
    def __init__( self, x, y, **kwdefaults ):
        super( AnotherSubClass, self ).__init__( x, y, **kwdefaults )
-4
ответ дан 28 November 2019 в 05:30
поделиться

Вы не можете сделать это с живым кодом.

То есть, похоже, вы хотите взять реальный, live, которая выглядит так:

def f(*args, **kwargs):
    print args[0]

и измените ее на такую:

def f(a):
    print a

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

В результате получается функция, которая получает два параметра: список и dict, а код, который вы пишете, работает с этим списком и dict. Второй результат дает функцию, которая получает один параметр и к которой обращаются напрямую как к локальной переменной. Если вы, так сказать, измените "подпись" функции, это приведет к такой функции:

def f(a):
    print a[0]

, которая явно не будет работать.

Если вам нужны более подробные сведения (хотя на самом деле это вам не поможет ), функция, которая принимает * args или * kwargs, имеет один или два бита, установленных в f.func_code.co_flags ; вы можете проверить это сами. Функция, которая принимает обычный параметр, имеет значение f.func_code.co_argcount , равное 1; версия * args - 0. Это то, что Python использует, чтобы выяснить, как настроить фрейм стека функции при ее вызове, для проверки параметров и т. д.

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

Тем не менее, вы можете динамически изменять строку документации функции. Просто назначьте func .__ doc __ . Обязательно делайте это только во время загрузки (из глобального контекста или, скорее всего, из декоратора);

1
ответ дан 28 November 2019 в 05:30
поделиться

Редактировать 1: Ответ на новый вопрос:

Вы спрашиваете, как можно создать функцию с этой сигнатурой:

def fun(a, b, opt=None):
    pass

Правильный способ сделать это в Python:

def fun(a, b, opt=None):
    pass

Редактировать 2: Ответ на объяснение:

«Предположим, у меня есть универсальная функция f. Я хочу программно создать функцию f2, которая ведет себя так же, как f, но имеет настраиваемую подпись».

def f(*args, **kw):
    pass

Хорошо, тогда f2 выглядит так:

def f2(a, b, opt=None):
    f(a, b, opt=opt)

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

-5
ответ дан 28 November 2019 в 05:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: