Строки в Java неизменяемы. Это означает, что всякий раз, когда вы пытаетесь изменить / изменить строку, вы получаете новый экземпляр. Вы не можете изменить исходную строку. Это сделано для того, чтобы эти экземпляры строк могли кэшироваться. Типичная программа содержит множество ссылок на строки и кеширование этих экземпляров, что может уменьшить объем памяти и увеличить производительность программы.
При использовании оператора == для сравнения строк вы не сравниваете содержимое строки , но фактически сравнивают адрес памяти. Если они равны, в противном случае они вернут true и false. Если значение равно в строке, сравнивает содержимое строки.
Итак, вопрос в том, что все строки кэшируются в системе, как получается ==
возвращает false, тогда как equals возвращает true? Ну, это возможно. Если вы создадите новую строку, например String str = new String("Testing")
, вы создадите новую строку в кеше, даже если в кеше уже содержится строка с тем же содержимым. Короче говоря, "MyString" == new String("MyString")
всегда будет возвращать false.
Java также говорит о функции intern (), которая может использоваться в строке, чтобы сделать ее частью кеша, поэтому "MyString" == new String("MyString").intern()
вернет true.
Примечание: == оператор намного быстрее, чем равен только потому, что вы сравниваете два адреса памяти, но вы должны быть уверены, что код не создает новые экземпляры String в коде. В противном случае вы столкнетесь с ошибками.
Вы можете следовать рекомендациям в PEP 3101 и использовать подкласс Formatter:
import string
class BlankFormatter(string.Formatter):
def __init__(self, default=''):
self.default=default
def get_value(self, key, args, kwds):
if isinstance(key, str):
return kwds.get(key, self.default)
else:
return string.Formatter.get_value(key, args, kwds)
kwargs = {"name": "mark", "adj": "mad"}
fmt=BlankFormatter()
print fmt.format("My name is {name} and I'm really {adj}.", **kwargs)
# My name is mark and I'm really mad.
print fmt.format("My name is {name} and I'm really {adjective}.", **kwargs)
# My name is mark and I'm really .
Начиная с Python 3.2 вы можете использовать .format_map в качестве альтернативы:
class Default(dict):
def __missing__(self, key):
return '{'+key+'}'
kwargs = {"name": "mark"}
print("My name is {name} and I'm really {adjective}.".format_map(Default(kwargs)))
, который печатает:
My name is mark and I'm really {adjective}.
Вот один из вариантов, который использует collections.defaultdict
:
>>> from collections import defaultdict
>>> kwargs = {"name": "mark"}
>>> template = "My name is {0[name]} and I'm really {0[adjective]}."
>>> template.format(defaultdict(str, kwargs))
"My name is mark and I'm really ."
Обратите внимание, что мы не используем **
, чтобы больше распаковать словарь в аргументы ключевых слов и спецификатор формата использует {0[name]}
и {0[adjective]}
, что указывает, что мы должны выполнить ключевой поиск по первому аргументу в format()
, используя "name"
и "adjective"
соответственно. С помощью defaultdict
отсутствующий ключ приведет к пустой строке вместо повышения KeyError.
Для записи:
s = "My name is {name} and I'm really {adjective}."
kwargs = dict((x[1], '') for x in s._formatter_parser())
# Now we have: `kwargs = {'name':'', 'adjective':''}`.
kwargs.update(name='mark')
print s.format(**kwargs) # My name is mark and I'm really .
Хотелось добавить довольно простое решение для замены любых значений по умолчанию.
import string
class SafeDict(dict):
def __init__(self, missing='#', empty='', *args, **kwargs):
super(SafeDict, self).__init__(*args, **kwargs)
self.missing = missing
self.empty = empty
def __getitem__(self, item):
return super(SafeDict, self).__getitem__(item) or self.empty
def __missing__(self, key):
return self.missing
values = SafeDict(a=None, c=1})
string.Formatter().vformat('{a} {c} {d}', (), values)
# ' 1 #'
Способ избежать ключевой ошибки состоит в том, чтобы включить в dict, но оставить его пустым:
kwargs = {"name": "mark", "adjective": ""}
"My name is {name} and I'm really {adjective}.".format(**kwargs)
Аргументы ключевого слова ожидают, что они будут ключом в kwargs. Другой способ сделать это - позиционные аргументы:
"My name is {0} and I'm really {1}.".format("mark")
Печать: «Меня зовут Марк, и я на самом деле». В то время как
"My name is {0} and I'm really {1}.".format("mark","black")
Печатает «Меня зовут Марк, и я действительно черный».
Кроме того, вы можете поймать ValueError.
assert
раньше времени, чтобы убедиться, что прилагательное по умолчанию инициализируется пустым в словаре.
– Tommy
5 November 2013 в 23:59
or isinstance(key, unicode)
– Nimo 4 June 2014 в 13:22Formatter
бытьstring.Formatter
? Может ли этаelse
часть быть достигнута? – Elias Zamaria 1 November 2016 в 18:11return string.Formatter
, и это было исправлено.else
достигается, если вы используете форматирование индексации кортежа, например"one {0} two {1}".format(1,2)
, вместо доступа к ключевому слову. Спасибо за комментарий. Исправлена ошибка в течение трех лет! – dawg 8 March 2017 в 17:33