2355

Is there a way to substring a string in Python, to get a new string from the third character to the end of the string?

Maybe like myString[2:end]?

If leaving the second part means 'till the end', and if you leave the first part, does it start from the start?

lospejos
  • 1,888
  • 3
  • 17
  • 31
Joan Venge
  • 269,545
  • 201
  • 440
  • 653

14 Answers14

3428
>>> x = "Hello World!"
>>> x[2:]
'llo World!'
>>> x[:2]
'He'
>>> x[:-2]
'Hello Worl'
>>> x[-2:]
'd!'
>>> x[2:-2]
'llo Worl'

Python calls this concept "slicing" and it works on more than just strings. Take a look here for a comprehensive introduction.

Community
  • 1
  • 1
Paolo Bergantino
  • 449,396
  • 76
  • 509
  • 431
433

Just for completeness as nobody else has mentioned it. The third parameter to an array slice is a step. So reversing a string is as simple as:

some_string[::-1]

Or selecting alternate characters would be:

"H-e-l-l-o- -W-o-r-l-d"[::2] # outputs "Hello World"

The ability to step forwards and backwards through the string maintains consistency with being able to array slice from the start or end.

Endophage
  • 19,217
  • 9
  • 54
  • 85
  • 23
    @mtahmed absolutely related to question. What if you wanted to substring by selecting alternate characters from the string? That would be my_string[::2] – Endophage Feb 12 '13 at 17:59
  • I think it's more likely you wanted to mention the third parameter to slice. Needing to get every other character from a string may be an important use case somewhere, but I've never had to do it. Not that there's anything wrong with wanting to show off what you know -- what's the point of knowing things if you can't do that. :) But the case for relevance to the question is overstated. – John Lockwood Dec 22 '17 at 11:03
  • 2
    Sure, the specific example of selecting alternate characters may not be relevant to the question, but understanding there is a 3rd parameter to slicing very much is relevant and the simple examples serve to illustrate how it works. The Python community also has a great history of educating new members in a friendly way :-) – Endophage Jan 04 '18 at 18:47
  • It is clear that if you put some_string[::-1] you got back, the string in reverse order. However, I really don't understand what you do in this case with the other numbers? Ex.: test_string[5:1:-1] - will result a totally different way that I expect. How the first and second numbers will effect the string if the third number is "-1" ? – Zoliqa Mar 21 '21 at 23:03
141

Substr() normally (i.e. PHP and Perl) works this way:

s = Substr(s, beginning, LENGTH)

So the parameters are beginning and LENGTH.

But Python's behaviour is different; it expects beginning and one after END (!). This is difficult to spot by beginners. So the correct replacement for Substr(s, beginning, LENGTH) is

s = s[ beginning : beginning + LENGTH]
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Michał Leon
  • 1,725
  • 1
  • 12
  • 12
  • 85
    The beginners should learn the pythonic way when moving to python, not stick to other language habits – Nicu Surdu May 29 '13 at 13:58
  • 3
    And just for completeness, Java is like Python in that the String.substring() method takes start and one-past-end. This one just bit me hard, I had assumed it was length like every other substring function in the world. – PhilHibbs Jan 10 '19 at 13:34
  • 6
    A (probably) more pythonic way to do that is `s[beginning:][:length]` – victortv Mar 12 '19 at 22:47
  • 2
    As someone who began with Python instead of [dirty word]-languages like PHP, I think Python is much more simple and intuitive with its string[beginning:end]. Length generally isn't relevant. – Gloweye Oct 09 '19 at 09:00
66

A common way to achieve this is by string slicing.

MyString[a:b] gives you a substring from index a to (b - 1).

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
codingscientist
  • 926
  • 1
  • 9
  • 12
27

One example seems to be missing here: full (shallow) copy.

>>> x = "Hello World!"
>>> x
'Hello World!'
>>> x[:]
'Hello World!'
>>> x==x[:]
True
>>>

This is a common idiom for creating a copy of sequence types (not of interned strings), [:]. Shallow copies a list, see Python list slice syntax used for no obvious reason.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
gimel
  • 73,814
  • 10
  • 69
  • 104
  • 15
    This has almost nothing to do with the question about substring. Doesn't even apply to string. Saying stringA = stringB is enough ... – Nicu Surdu May 29 '13 at 13:48
  • 2
    The [:] full copy creates a NEW COPY, uses slice syntax and is read as "substring from start to end" – gimel May 29 '13 at 14:31
  • 2
    What’s the point since strings are immutable? `a=b` should be sufficient. – bfontaine Dec 30 '16 at 21:21
  • 1
    @gimel: Actually, `[:]` on an immutable type doesn't make a copy at all. While `mysequence[:]` is mostly harmless when `mysequence` is an immutable type like `str`, `tuple`, `bytes` (Py3) or `unicode` (Py2), `a = b[:]` is equivalent to `a = b`, it just wastes a little time dispatching the slicing byte codes which the object responds to by returning itself since it's pointless to shallow copy when, aside from object identity tests, it's equivalent to just return another reference to one's immutable self. – ShadowRanger Jun 21 '17 at 19:29
  • 3
    Attempting to sum up the other criticisms of this answer: In Python, strings are immutable, therefore there is no reason to make a copy of a string - so `s[:]` doesn't make a copy at all: `s = 'abc'; s0 = s[:]; assert s is s0`. Yes it was the idiomatic way to copy a list in Python until lists got `list.copy`, but a full slice of an immutable type has no reason to make a copy because it can't be changed, so there may as well be only one in memory and we shouldn't waste time copying it. Since this answer is wrong and **doesn't even answer the question** - should it be deleted? – Aaron Hall Oct 25 '17 at 14:33
19

Is there a way to substring a string in Python, to get a new string from the 3rd character to the end of the string?

Maybe like myString[2:end]?

Yes, this actually works if you assign, or bind, the name,end, to constant singleton, None:

>>> end = None
>>> myString = '1234567890'
>>> myString[2:end]
'34567890'

Slice notation has 3 important arguments:

  • start
  • stop
  • step

Their defaults when not given are None - but we can pass them explicitly:

>>> stop = step = None
>>> start = 2
>>> myString[start:stop:step]
'34567890'

If leaving the second part means 'till the end', if you leave the first part, does it start from the start?

Yes, for example:

>>> start = None
>>> stop = 2
>>> myString[start:stop:step]
'12'

Note that we include start in the slice, but we only go up to, and not including, stop.

When step is None, by default the slice uses 1 for the step. If you step with a negative integer, Python is smart enough to go from the end to the beginning.

>>> myString[::-1]
'0987654321'

I explain slice notation in great detail in my answer to Explain slice notation Question.

Community
  • 1
  • 1
Aaron Hall
  • 291,450
  • 75
  • 369
  • 312
8

You've got it right there except for "end". It's called slice notation. Your example should read:

new_sub_string = myString[2:]

If you leave out the second parameter it is implicitly the end of the string.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
bouvard
  • 3,766
  • 22
  • 28
7

I would like to add two points to the discussion:

  1. You can use None instead on an empty space to specify "from the start" or "to the end":

    'abcde'[2:None] == 'abcde'[2:] == 'cde'
    

    This is particularly helpful in functions, where you can't provide an empty space as an argument:

    def substring(s, start, end):
        """Remove `start` characters from the beginning and `end` 
        characters from the end of string `s`.
    
        Examples
        --------
        >>> substring('abcde', 0, 3)
        'abc'
        >>> substring('abcde', 1, None)
        'bcde'
        """
        return s[start:end]
    
  2. Python has slice objects:

    idx = slice(2, None)
    'abcde'[idx] == 'abcde'[2:] == 'cde'
    
ostrokach
  • 12,120
  • 6
  • 59
  • 78
7

If myString contains an account number that begins at offset 6 and has length 9, then you can extract the account number this way: acct = myString[6:][:9].

If the OP accepts that, they might want to try, in an experimental fashion,

myString[2:][:999999]

It works - no error is raised, and no default 'string padding' occurs.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
CopyPasteIt
  • 446
  • 7
  • 18
  • 1
    I think if you want to use this method `myString[offset:][:length]` in the case of OP you can just use `myString[offset:][:]` – victortv Mar 12 '19 at 22:49
  • 1
    @VictorVal The answer is for those (like me) who have learned Python as a 2nd (3rd, 4th, ...) programming language and want to some familiar 'syntax hooks' to approach the language. Any experts in the language will most likely view my answer as a bit silly. – CopyPasteIt Mar 12 '19 at 22:58
  • Should answers like this be flagged for deletion? Other answers explain similar solution much better, and seeing this one had made me scratch my head and lookup python for few minutes before realising that it's just that type answer. – Sebi Jun 12 '19 at 08:10
6

Well, I got a situation where I needed to translate a PHP script to Python, and it had many usages of substr(string, beginning, LENGTH).
If I chose Python's string[beginning:end] I'd have to calculate a lot of end indexes, so the easier way was to use string[beginning:][:length], it saved me a lot of trouble.

Edson Horacio Junior
  • 2,451
  • 2
  • 23
  • 39
4

Maybe I missed it, but I couldn't find a complete answer on this page to the original question(s) because variables are not further discussed here. So I had to go on searching.

Since I'm not yet allowed to comment, let me add my conclusion here. I'm sure I was not the only one interested in it when accessing this page:

 >>>myString = 'Hello World'
 >>>end = 5

 >>>myString[2:end]
 'llo'

If you leave the first part, you get

 >>>myString[:end]
 'Hello' 

And if you left the : in the middle as well you got the simplest substring, which would be the 5th character (count starting with 0, so it's the blank in this case):

 >>>myString[end]
 ' '
Rudi Uhl
  • 65
  • 2
2

Using hardcoded indexes itself can be a mess.

In order to avoid that, Python offers a built-in object slice().

string = "my company has 1000$ on profit, but I lost 500$ gambling."

If we want to know how many money I got left.

Normal solution:

final = int(string[15:19]) - int(string[43:46])
print(final)
>>>500

Using slices:

EARNINGS = slice(15, 19)
LOSSES = slice(43, 46)
final = int(string[EARNINGS]) - int(string[LOSSES])
print(final)
>>>500

Using slice you gain readability.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
levi
  • 19,165
  • 7
  • 56
  • 68
  • 5
    Maybe this isn't the best example, because the hardcoded indexes remain and the readability comes from intermediate variables, which you could have used in the first example. – ASalazar Jan 25 '17 at 17:27
0
a="Helloo"
print(a[:-1])

In the above code, [:-1] declares to print from the starting till the maximum limit-1.

OUTPUT :

>>> Hello

Note: Here a [:-1] is also the same as a [0:-1] and a [0:len(a)-1]

a="I Am Siva"
print(a[2:])

OUTPUT:

>>> Am Siva

In the above code a [2:] declares to print a from index 2 till the last element.

Remember that if you set the maximum limit to print a string, as (x) then it will print the string till (x-1) and also remember that the index of a list or string will always start from 0.

0
str1='There you are'
>>> str1[:]
'There you are'

>>> str1[1:]
'here you are'

#To print alternate characters skipping one element in between

>>> str1[::2]
'Teeyuae'

#To print last element of last two elements
>>> str1[:-2:-1]
'e'

#Similarly
>>> str1[:-2:-1]
'e'


#Using slice datatype

>>> str1='There you are'
>>> s1=slice(2,6)
>>> str1[s1]
'ere '


Harsh
  • 41
  • 1