tldr; format
просто вызывает obj.__format__
и используется str.format
методом, который выполняет еще более высокоуровневые функции. Для нижнего уровня имеет смысл научить объект форматироваться.
Это просто синтаксический сахар
Тот факт, что эта функция разделяет имя и спецификацию формата с str.format
, может вводить в заблуждение. Существование str.format
легко объяснить: он выполняет сложную интерполяцию строк (заменяя старый оператор %
); format
может форматировать отдельный объект как строку, наименьшее подмножество str.format
спецификации. Итак, зачем нам format
?
Функция format
является альтернативой конструкции obj.format('fmt')
, которая есть в некоторых языках OO. Это решение согласуется с обоснованием len
(почему Python использует функцию len(x)
вместо свойства x.length
, например Javascript или Ruby).
Когда язык принимает конструкцию obj.format('fmt')
(или obj.length
, obj.toString
и т. Д.), Классы не могут иметь атрибут с именем format
(или length
, toString
, вы уловили идею) - в противном случае он бы затенял стандартный метод языка. В этом случае разработчики языка перекладывают бремя предотвращения конфликтов имен на программиста.
Python очень любит PoLA и принял соглашение __dunder__
(двойное подчеркивание) для встроенных в чтобы свести к минимуму вероятность конфликтов между определяемыми пользователем атрибутами и встроенными языками. Итак, obj.format('fmt')
становится obj.__format__('fmt')
, и, конечно, вы можете вызвать obj.__format__('fmt')
вместо format(obj, 'fmt')
(точно так же вы можете вызвать obj.__len__()
вместо len(obj)
).
Используя ваш пример:
>>> '{0:x}'.format(13)
'd'
>>> (13).__format__('x')
'd'
>>> format(13, 'x')
'd'
Какой из них чище и легче набирать? Дизайн Python очень прагматичен, он не только чище, но и хорошо согласуется с утиным типом в Python. подход к OO и дает разработчикам языка свободу изменять / расширять базовую реализацию без нарушения устаревшего код.
PEP 3101 представил новый метод str.format
и встроенный format
без каких-либо комментариев. в обосновании функции format
, но реализация, очевидно, представляет собой просто синтаксический сахар:
def format(value, format_spec):
return value.__format__(format_spec)
И здесь я отдыхаю.
Что Гвидо сказал по этому поводу (или это официально?)
Цитата из самого BDFL о len
:
Прежде всего, я выбрал len(x)
вместо x.len()
по причинам HCI (пришло def __len__()
гораздо позже). На самом деле есть две взаимосвязанные причины, обе HCI:
(a) Для некоторых операций префиксная нотация просто читается лучше, чем постфиксная - префиксные (и инфиксные!) операции имеют давнюю традицию в математике, которой нравятся нотации, в которых визуальные элементы помогают математику думать о проблеме. Сравните легкость, с которой мы переписываем формулу типа x*(a+b)
в x*a + x*b
, с неуклюжестью выполнения того же самого с использованием необработанной объектно-ориентированной нотации.
(б) Когда я читаю код, который говорит len(x)
, я знаю, что он запрашивает длину чего-то. Это говорит мне о двух вещах: результат - целое число, а аргумент - это своего рода контейнер. Напротив, когда я читаю x.len()
, я уже должен знать, что x
- это своего рода контейнер, реализующий интерфейс или наследующий от класса, имеющего стандартный len()
. Обратите внимание на путаницу, которая иногда возникает, когда класс, не реализующий сопоставление, имеет get()
или keys()
метод, или что-то, что не является файлом, имеет метод write()
.
Говоря то же самое по-другому, я вижу "len
" как встроенную операцию. Я бы не хотел это потерять. /… /
источник: [email protected] (исходное сообщение здесь также есть исходный вопрос, на который отвечал Гвидо). Абарнерт также предлагает:
Дополнительные аргументы относительно len в Часто задаваемые вопросы по дизайну и истории. Хотя это не такой полный или хороший ответ, он, бесспорно, официальный. - abarnert
Это практическая проблема или просто придирки к синтаксису?
Это очень практичная и реальная проблема для таких языков, как Python, Ruby или Javascript, потому что в динамически типизированных языках любой изменяемый объект фактически является пространством имен, а концепция частных методов или атрибутов является предметом соглашения. Возможно, я не смог бы выразить это лучше, чем abarnert в его комментарии:
Кроме того, что касается проблемы загрязнения пространства имен Ruby и JS, стоит отметить, что это неотъемлемая проблема языков с динамической типизацией. В таких разнообразных статически типизированных языках, как Haskell и C ++, бесплатные функции для конкретных типов не только возможны, но и идиоматичны. (См. принцип интерфейса.) Но в языках с динамической типизацией, таких как Ruby, JS и Python, бесплатные функции должны быть универсальными. Большая часть дизайна языка / библиотеки для динамических языков - это выбор правильного набора таких функций.
Например, я просто оставил Ember.js в пользу Angular.js, потому что мне надоело конфликты пространств имен в Ember; Angular обрабатывает это, используя элегантную стратегию, похожую на Python, с добавлением префиксов к встроенным методам (с $thing
в Angular вместо подчеркивания, как в python), поэтому они не конфликтуют с пользовательскими методами и свойствами. Да, в целом __thing__
не особо красив, но я рад, что Python использовал этот подход, потому что он очень явный и избегает PoLA класс ошибок, связанных с конфликтами пространств имен объектов.
person
Community
schedule
22.05.2013
format()
предпочтительнее.format()
- даже в документации по спецификациям строк формата везде используется.format()
. Откуда вы берете этоformat()
предпочтительнее? - person Amber   schedule 22.05.2013.format
- person jamylak   schedule 22.05.2013format
- person jamylak   schedule 22.05.2013