Есть еще одна проблема, которая не указана ни в одном из существующих ответов. Python разрешено объединять любые два неизменных значения, и предварительно созданные значения малых значений не являются единственным способом, которым это может случиться. Реализация Python никогда не гарантирована , но все они делают это не более, чем просто малые int.
Во-первых, есть еще некоторые предварительно созданные такие как пустые tuple
, str
и bytes
и некоторые короткие строки (в CPython 3.6 это 256 односимвольных строк Latin-1). Например:
>>> a = ()
>>> b = ()
>>> a is b
True
Но также даже не созданные заранее значения могут быть одинаковыми. Рассмотрим следующие примеры:
>>> c = 257
>>> d = 257
>>> c is d
False
>>> e, f = 258, 258
>>> e is f
True
И это не ограничено значениями int
:
>>> g, h = 42.23e100, 42.23e100
>>> g is h
True
Очевидно, что CPython не поставляется с предварительно созданным float
для параметра 42.23e100
. Итак, что здесь происходит?
Компилятор CPython будет объединять постоянные значения некоторых известных неизменяемых типов, таких как int
, float
, str
, bytes
, в одном модуле компиляции. Для модуля весь модуль является единицей компиляции, но в интерактивном интерпретаторе каждый оператор представляет собой отдельный блок компиляции. Поскольку c
и d
определены в отдельных утверждениях, их значения не объединяются. Поскольку e
и f
определены в том же самом заявлении, их значения сливаются.
Вы можете видеть, что происходит, разобрав байт-код. Попробуйте определить функцию, которая выполняет e, f = 128, 128
, а затем называет dis.dis
на ней, и вы увидите, что существует одно постоянное значение (128, 128)
>>> def f(): i, j = 258, 258
>>> dis.dis(f)
1 0 LOAD_CONST 2 ((128, 128))
2 UNPACK_SEQUENCE 2
4 STORE_FAST 0 (i)
6 STORE_FAST 1 (j)
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
>>> f.__code__.co_consts
(None, 128, (128, 128))
>>> id(f.__code__.co_consts[1], f.__code__.co_consts[2][0], f.__code__.co_consts[2][1])
4305296480, 4305296480, 4305296480
. Вы можете заметить, что компилятор сохранил 128
как константу, даже если он фактически не используется байтовым кодом, что дает вам представление о том, как мало оптимизирует компилятор CPython. Это означает, что (непустые) кортежи на самом деле не сливаются:
>>> k, l = (1, 2), (1, 2)
>>> k is l
False
Поместите это в функцию, dis
, и посмотрите на co_consts
- есть 1
и 2
, два (1, 2)
кортежа, которые имеют одинаковые 1
и 2
, но не идентичны, и кортеж ((1, 2), (1, 2))
, который имеет два разных одинаковых кортежа.
Есть еще одна оптимизация, которую выполняет CPython: string interning. В отличие от сгибания константы компилятора, это не ограничивается литералами исходного кода:
>>> m = 'abc'
>>> n = 'abc'
>>> m is n
True
С другой стороны, он ограничен типом str
и строками типа внутреннего хранилища «ascii compact», «compact» или «legacy ready» , и во многих случаях только «ascii compact» будет интернирован.
Во всяком случае, правила для чего значения должны быть, могут быть или не могут отличаться от реализации до реализации, а также между версиями одной и той же реализации и, возможно, даже между прогонами одного и того же кода в одной и той же копии одной и той же реализации.
Возможно, стоит изучить правила для одного конкретного Python для удовольствия. Но не стоит полагаться на них в вашем коде. Единственное безопасное правило:
Или, другими словами, использовать is
только для проверки документированных синглетов (например, None
) или которые создаются только в одном месте в код (например, идиома _sentinel = object()
).
urlparse модуль в Python 2.x (или urllib.parse в Python 3.x) был бы способом сделать это.
>>> from urllib.parse import urlparse
>>> url = 'http://example.com/random/folder/path.html'
>>> parse_object = urlparse(url)
>>> parse_object.netloc
'example.com'
>>> parse_object.path
'/random/folder/path.html'
>>> parse_object.scheme
'http'
>>>
, Если Вы хотели сделать больше работы над путем файла под URL, можно использовать posixpath модуль:
>>> from posixpath import basename, dirname
>>> basename(parse_object.path)
'path.html'
>>> dirname(parse_object.path)
'/random/folder'
После этого, можно использовать posixpath.join для склеивания частей.
РЕДАКТИРОВАНИЕ: Я полностью забыл, что пользователи Windows будут дросселировать на разделителе пути в os.path. Я прочитал posixpath документы модуля, и это имеет специальную ссылку на управление URL, таким образом, все хорошо.
У меня нет опыта с Python, но я нашел urlparse модуль , который должен сделать задание.
Если это будет степенью Вашего парсинга URL, то встроенный rpartition Python сделает задание:
>>> URL = "http://example.com/random/folder/path.html"
>>> Segments = URL.rpartition('/')
>>> Segments[0]
'http://example.com/random/folder'
>>> Segments[2]
'path.html'
От Pydoc, str.rpartition:
Splits the string at the last occurrence of sep, and returns a 3-tuple containing the part before the separator, the separator itself, and the part after the separator. If the separator is not found, return a 3-tuple containing two empty strings, followed by the string itself
то, Что это означает, - то, что rpartition делает поиск Вас и разделяет строку в последнем (право больше всего) возникновение символа, который Вы указываете (в этом случае/). Это возвращает кортеж, содержащий:
(everything to the left of char , the character itself , everything to the right of char)
В Python много операций сделано с помощью списков. urlparse модуль, упомянутый Sebasian Dietz, может решить Вашу определенную проблему, но если Вы обычно интересуетесь Pythonic способы найти, что наклонные черты в строках, например, пробуют что-то вроде этого:
url = 'http://example.com/random/folder/path.html'
# Create a list of each bit between slashes
slashparts = url.split('/')
# Now join back the first three sections 'http:', '' and 'example.com'
basename = '/'.join(slashparts[:3]) + '/'
# All except the last one
dirname = '/'.join(slashparts[:-1]) + '/'
print 'slashparts = %s' % slashparts
print 'basename = %s' % basename
print 'dirname = %s' % dirname
вывод этой программы - это:
slashparts = ['http:', '', 'example.com', 'random', 'folder', 'path.html'] basename = http://example.com/ dirname = http://example.com/random/folder/
интересные биты split
, join
, массив нотации части [A:B] (включая отрицательные стороны для offsets-from-the-end) и, в качестве награды, %
оператор на строках для предоставления форматирования printf-стиля.