Из источников Python object.c:
/* Test whether an object can be called */
int
PyCallable_Check(PyObject *x)
{
if (x == NULL)
return 0;
if (PyInstance_Check(x)) {
PyObject *call = PyObject_GetAttrString(x, "__call__");
if (call == NULL) {
PyErr_Clear();
return 0;
}
/* Could test recursively but don't, for fear of endless
recursion if some joker sets self.__call__ = self */
Py_DECREF(call);
return 1;
}
else {
return x->ob_type->tp_call != NULL;
}
}
Это говорит:
__call__
атрибут. x
вызываемый эквивалентность x->ob_type->tp_call != NULL
Desciption [1 118] tp_call
поле :
ternaryfunc tp_call
дополнительный указатель на функцию, которая реализует вызов объекта. Это должно быть ПУСТЫМ, если объект не является вызываемым. Подпись совпадает с для PyObject_Call (). Это поле наследовано подтипами.
можно всегда использовать встроенный callable
функция, чтобы определить, является ли данный объект вызываемым или нет; или еще лучше просто назовите его и поймайте TypeError
позже. callable
удален в Python 3.0 и 3.1, используйте callable = lambda o: hasattr(o, '__call__')
или isinstance(o, collections.Callable)
.
Пример, упрощенная реализация кэша:
class Cached:
def __init__(self, function):
self.function = function
self.cache = {}
def __call__(self, *args):
try: return self.cache[args]
except KeyError:
ret = self.cache[args] = self.function(*args)
return ret
Использование:
@Cached
def ack(x, y):
return ack(x-1, ack(x, y-1)) if x*y else (x + y + 1)
Пример из стандартной библиотеки, файла site.py
, определения встроенных exit()
и quit()
функции:
class Quitter(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Use %s() or %s to exit' % (self.name, eof)
def __call__(self, code=None):
# Shells like IDLE catch the SystemExit, but listen when their
# stdin wrapper is closed.
try:
sys.stdin.close()
except:
pass
raise SystemExit(code)
__builtin__.quit = Quitter('quit')
__builtin__.exit = Quitter('exit')
Шаблон приложения на основе Core Data в Xcode предоставляет этот метод:
- (NSString *)applicationDocumentsDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
Таким образом, похоже, что Apple продолжает поддерживать получение каталога документов таким образом. Я полагаю, вы можете поместить его в категорию, но я обнаружил, что достаточно включить этот метод в небольшую горстку классов в данном приложении, которые должны выполнять работу в каталоге документов. Если вы делаете много файловой работы повсюду, вы можете подумать о небольшом рефакторинге своего кода, чтобы ограничить эти задачи одним или двумя классами менеджеров.
Для меня, по крайней мере, в третий или четвертый раз я сказал «Эй, получить каталог с документами - это головная боль» - это тот момент, когда я реализовал некоторые возможности перенести манипулирование файлами в специальный класс.
This works for me, pretty short and sweet
#define kDOCSFOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]
Cheers!