Just encountering this problem, it baffles me! My code just wants to compare song[-3:] is "mp3" which would, if I didn't use is, pass, but through all the patience I have with things out of my comprehension, I've found a peculiar behavior. I learned that is supposedly tests to see if two things are the same instance or whatever, but when the value IS the same, why, oh why, does it fail? When I test the id of two strings on one line, another line, using the is operator, then the == operator:
>>> id("String"[-3:]), id("String"[-3:])
(4347723880, 4347723880)
>>> id("String"[-3:])
4347241952
>>> "String"[-3:] is "String"[-3:]
False
>>> "String"[-3:] == "String"[-3:]
True
so I suppose my question is, why does the id change when when I use is, or when tested on a separate line, but not when on the same line? Is this some strange exception, or is this some oversight on my part?
is tests if they are the same string, not just identical strings. Since strings are immutable, Python can choose to reuse old strings if you ask for one with the same value - you are encountering some situations where it does choose to do this. As you've seen, it doesn't always. The rules for when it does aren't guaranteed. To get the right result in all circumstances, use str1 == str2 whenever you mean "do these strings have all the same letters".
It happens because when you do:
"String"[-3:] is "String"[-3:]
python creates two different objects with different id.
When you call "String"[-3:], python gives you a string object. And if there is a same str. Two str should be the same. But if you dont assign "String"[-3:] to a varible.The "String"[-3:] will be "disapeared". I tested if you use a="String"[-3:]. then the id of "String"[-3:] wouln't change anymore
Related
This question already has answers here:
Remove all occurrences of a value from a list?
(26 answers)
Closed 2 years ago.
So I want to execute only while loop statements, without putting anything inside them. For example, I have an array arr from which I have to remove multiple occurrences of some element. The instant the condition statement returns an error, while loop should end.
arr=[1,2,4,2,4,2,2]
This removes only one 2:
arr.remove(2)
I need to run this as long as it does not return error. (C++ has a semicolon put after while to do this).
I want something like this
while(arr.remove(2));
Three things.
First, it's not considered good practice in Python – it's not "pythonic" – to use an expression for its side effects. This is why, for example, the Python assignment operator is not itself an expression. (Although you can do something like a = b = 1 to set multiple variables to the same value, that statement doesn't break down as a = (b = 1); any such attempt to use an assignment statement as a value is a syntax error.)
Second, modifying data in place is also discouraged; it's usually better to make a copy and make the changes as the copy is constructed.
Third, even if this were a good way to do things, it wouldn't work in this case. When the remove method succeeds, it returns None, which is not truthy, so your loop exits immediately. On the other hand, when it fails, instead of returning a false value, it throws an exception, which will abort your whole program instead of just the loop, unless you wrap it in a try block.
So the list comprehension probably is the best solution here.
The way you are looking to solve this does not yield the results you are looking for. Since you are looking to create a new list, you are not going to want to use the remove function as per #Matthias comment. The idiomatic way to do it would be something along the lines of this:
arr=[1,2,4,2,4,2,2]
arr = [x if x != 2 for x in arr]
So I want to execute only while loop statements, without putting anything inside them.
That's really not necessary. Don't try to copy other language's syntax in Python. Different languages are designed with different objectives and hence, they have different syntax (or grammar of the language). Python has a different way of doing things than C++.
If you want to focus on the effectiveness of the program, then that's the different story. See this for more information on this.
Unfortunately, remove doesn't return anything (it returns None). So, you can't have anything that would look neat and clean without putting anything inside while.
Pythonic way to remove all occurrence of a element from list:
list(filter((2).__ne__, arr))
Or
arr = [x for x in arr if x != 2]
Or
while 2 in arr:
arr.remove(2)
you can use:
arr = [1,2,4,2,4,2,2]
try:
while arr.pop(arr.index(2)):
pass
except ValueError:
pass
print(arr)
#[1, 4, 4]
I am assuming you want to remove all occurrences of an element. This link might help you.
click here
so I wnt to compare a string in a iist and variable but the output is awlays false
ive used is and == then I thought because elemen in my list is not string then I try to chnage it in to a str using str() func but it doesnt work
obj='ana'
# haha[22][0] is 'ana'
obj1=str(haha[22][0])
if obj is obj1:
print('true')
else:
print('false')
print(obj1)
first I tried to change == into is but it doesnt work then I though I need to change elemen in my list into str() it doenst work too
I would like to compare it thank you so much for the answer
This is almost certainly something to do with what's stored in your list. Also in general == is for comparing value and 'is' is for comparing identity so you should use == in this situation.
What is output by the last print?
'ana' == 'ana' will always return true so without specifying where the element is set there isn't enough information to work out what your issue is.
If it prints 'ana' it may be worth printing the hash function of each object to compare.
I'd like to have written this as a comment but I don't have enough rep to comment :/
I'm having trouble in an online course for python, specifically a palindrome problem These are the instructions, but the function must be case-insensitive and not see spaces. I think the issue is in my return blocks or my flow. I think I need to use the lower function, but I'm honestly not sure.
def student_func(x):
for string in x:
x.lower()
y = x.replace(" ", "")
if y[::-1]==y:
return True
else:
return False
You actually have two separate problems in your code—and you're right that one of them is with lower and the other is with the return flow.
First, x.lower() doesn't modify x in-place. In fact, strings are immutable; nothing modifies them in-place. If you look up the interactive help or the online docs, it says:
Return a copy of the string with all the cased characters [4] converted to lowercase.
So, you need to do the same thing with lower that you do with replace: assign the result to a variable, and use that:
y = x.lower()
z = y.replace(" ", "")
Or you can reuse the same variable:
x = x.lower()
… or chain the two calls together:
y = x.lower().replace(" ", "")
As a side note, unless you're using Python 2, you should consider whether you want casefold instead of lower. For English it makes no difference, but for other languages it can.
Meanwhile, you're doing for string in x:, but then ignoring string.
If x is just a single word, you don't want to loop over it at all.
If x is a list of words, then the for string in x: is correct, but then you have to use string inside the loop, not x. Plus, you can't just return True or return False—that will exit the function as soon as you test the first word, meaning the rest of them never get tested. I'm not sure whether you want to return True if there are any pallidromes, or if they're all palindromes, or if you want to return a list of booleans instead of a single one, or what, but you can't just return the first one.
It would probably be a lot clearer if you used better names, like words instead of x and word instead of string.
Anyway, I can't tell you the right way to fix this since I don't know what you're trying to do, but hopefully this explains enough that you can fix it yourself.
Giving away the solution defeats the purpose of the exercise
your approach is more or less correct.
convert string to a standard case
remove whitespace
check if reverse of the string is equal to the original string
The error lies in how you are using the python API.
check what each of the functions do, and what they return.
a good idea is to run help(function) to see what the function's documentation has to say about it.
try help(x.lower) (note: not help(x.lower())) and see what the return value is.
While I know that there is the possibility:
>>> a = "abc"
>>> result = a[-1]
>>> a = a[:-1]
Now I also know that strings are immutable and therefore something like this:
>>> a.pop()
c
is not possible.
But is this really the preferred way?
Strings are "immutable" for good reason: It really saves a lot of headaches, more often than you'd think. It also allows python to be very smart about optimizing their use. If you want to process your string in increments, you can pull out part of it with split() or separate it into two parts using indices:
a = "abc"
a, result = a[:-1], a[-1]
This shows that you're splitting your string in two. If you'll be examining every byte of the string, you can iterate over it (in reverse, if you wish):
for result in reversed(a):
...
I should add this seems a little contrived: Your string is more likely to have some separator, and then you'll use split:
ans = "foo,blah,etc."
for a in ans.split(","):
...
Not only is it the preferred way, it's the only reasonable way. Because strings are immutable, in order to "remove" a char from a string you have to create a new string whenever you want a different string value.
You may be wondering why strings are immutable, given that you have to make a whole new string every time you change a character. After all, C strings are just arrays of characters and are thus mutable, and some languages that support strings more cleanly than C allow mutable strings as well. There are two reasons to have immutable strings: security/safety and performance.
Security is probably the most important reason for strings to be immutable. When strings are immutable, you can't pass a string into some library and then have that string change from under your feet when you don't expect it. You may wonder which library would change string parameters, but if you're shipping code to clients you can't control their versions of the standard library, and malicious clients may change out their standard libraries in order to break your program and find out more about its internals. Immutable objects are also easier to reason about, which is really important when you try to prove that your system is secure against particular threats. This ease of reasoning is especially important for thread safety, since immutable objects are automatically thread-safe.
Performance is surprisingly often better for immutable strings. Whenever you take a slice of a string, the Python runtime only places a view over the original string, so there is no new string allocation. Since strings are immutable, you get copy semantics without actually copying, which is a real performance win.
Eric Lippert explains more about the rationale behind immutable of strings (in C#, not Python) here.
The precise wording of the question makes me think it's impossible.
return to me means you have a function, which you have passed a string as a parameter.
You cannot change this parameter. Assigning to it will only change the value of the parameter within the function, not the passed in string. E.g.
>>> def removeAndReturnLastCharacter(a):
c = a[-1]
a = a[:-1]
return c
>>> b = "Hello, Gaukler!"
>>> removeAndReturnLastCharacter(b)
!
>>> b # b has not been changed
Hello, Gaukler!
Yes, python strings are immutable and any modification will result in creating a new string. This is how it's mostly done.
So, go ahead with it.
I decided to go with a for loop and just avoid the item in question, is it an acceptable alternative?
new = ''
for item in str:
if item == str[n]:
continue
else:
new += item
This question already has answers here:
About the changing id of an immutable string
(5 answers)
Closed 4 years ago.
Why does "hello" is "hello" produce True in Python?
I read the following here:
If two string literals are equal, they have been put to same
memory location. A string is an immutable entity. No harm can
be done.
So there is one and only one place in memory for every Python string? Sounds pretty strange. What's going on here?
Python (like Java, C, C++, .NET) uses string pooling / interning. The interpreter realises that "hello" is the same as "hello", so it optimizes and uses the same location in memory.
Another goodie: "hell" + "o" is "hello" ==> True
So there is one and only one place in memory for every Python string?
No, only ones the interpreter has decided to optimise, which is a decision based on a policy that isn't part of the language specification and which may change in different CPython versions.
eg. on my install (2.6.2 Linux):
>>> 'X'*10 is 'X'*10
True
>>> 'X'*30 is 'X'*30
False
similarly for ints:
>>> 2**8 is 2**8
True
>>> 2**9 is 2**9
False
So don't rely on 'string' is 'string': even just looking at the C implementation it isn't safe.
Literal strings are probably grouped based on their hash or something similar. Two of the same literal strings will be stored in the same memory, and any references both refer to that.
Memory Code
-------
| myLine = "hello"
| /
|hello <
| \
| myLine = "hello"
-------
The is operator returns true if both arguments are the same object. Your result is a consequence of this, and the quoted bit.
In the case of string literals, these are interned, meaning they are compared to known strings. If an identical string is already known, the literal takes that value, instead of an alternative one. Thus, they become the same object, and the expression is true.
The Python interpreter/compiler parses the string literals, i.e. the quoted list of characters. When it does this, it can detect "I've seen this string before", and use the same representation as last time. It can do this since it knows that strings defined in this way cannot be changed.
Why is it strange. If the string is immutable it makes a lot of sense to only store it once. .NET has the same behavior.
I think if any two variables (not just strings) contain the same value, the value will be stored only once not twice and both the variables will point to the same location. This saves memory.