Другое событие 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));
}
Для вашего варианта использования наличие строки документации в классе / функции должно работать - это будет отображаться в 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 должно дать вам полное решение. Но, эээ ...
Возможно, я не знал » Я хорошо понимаю проблему, но если речь идет о сохранении того же поведения при изменении сигнатуры функции, то вы можете сделать что-то вроде:
# 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
Мы хотим, чтобы
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 )
Вы не можете сделать это с живым кодом.
То есть, похоже, вы хотите взять реальный, 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: Ответ на новый вопрос:
Вы спрашиваете, как можно создать функцию с этой сигнатурой:
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)
Опять же, ответ на ваш вопрос настолько тривиален, что вы, очевидно, хотите знать нечто иное, чем то, о чем вы спрашиваете. Вам действительно нужно перестать задавать абстрактные вопросы и объяснять вашу конкретную проблему.