Reputation:
Wanted to see if I'm going in the right direction. I have to change everything but the last four characters of a string into #. I've got two ideas so far.
First one:
def maskify(cc):
cc = raw_input("Enter passcode: ")
n = len(cc)
cc.replace(cc[0:n-4], #) # this one gives me the unexpected EOF while parsing error
Second one (I think this one's closer because it supposedly needs an algorithm):
def maskify(cc):
cc = raw_input("Enter passcode: ")
n = len(cc)
for i in range (0, n-4): # i think a for loop would be good but i don't know how i'm going to use it yet
cc.replace( #not entirely sure what to put here
pass
Upvotes: 1
Views: 3084
Reputation: 1
# return masked string
def maskify(cc):
maskify = cc
maskifyL= len(maskify) - 4
char = ""
a=0
if maskifyL <= 2:
c2 = cc
else:
for a in range(maskifyL):
char += "#"
a += 1
c2 = maskify.replace(maskify[:maskifyL], char, maskifyL)
return c2
Upvotes: 0
Reputation: 2190
cc = raw_input("Enter passcode: ")
cc = ''.join(('#' * (len(cc) - 4), cc[-4:]))
Upvotes: 3
Reputation: 818
First of all strings are immutable(they can't be changed) once created--so you can't change the value of cc with replace(). To change all parts of the string except the last four, do this:
def doso(text):
assert len(str(text))>4, 'Length of text should be >4'
ctext=str(text).replace(str(text)[:(len(str(text))-4)],'#'*(len(str(text))-4))
print(ctext)
>>>doso(123) prints 'Length of text should be >4' because len(text)== 3 which is what we expect
Hovever,
>>>doso(12345678) prints #####6789 which is exactly what we expect
Note: Doing '#' * (len(str(text))-4)) accounts for the number of characters we want to replace
Upvotes: 0
Reputation: 1210
How about the following?
def maskify() :
cc = input("Enter passcode: ")
mask = '#'*(len(cc)-4)
return mask + cc[-4:]
I'm not sure how the flow of the rest of your program works, but I doubt whether you should be prompting for raw_input inside of this function. You can decide that depending on your needs. The alternative would look something like this:
def maskify(cc) :
return '#'*(len(cc)-4) + cc[-4:]
myInput = input("Enter passcode: ")
maskedInput = maskify( myInput )
raw_input
instead of input
Upvotes: 2
Reputation: 46759
The following solution makes the assumption that this would have a security type use, as such passcodes of 4 or fewer characters should just be hashed, otherwise someone would know the whole passcode.
def maskify(cc):
if len(cc) < 9:
split = [0,1,2,3,4,4,4,4,4][len(cc)]
else:
split = len(cc) - 4
return "#" * split + cc[split:]
for length in range(1,12):
test = string.lowercase[:length]
print "%s > %s" % (test, maskify(test))
Giving the following results:
a > #
ab > ##
abc > ###
abcd > ####
abcde > ####e
abcdef > ####ef
abcdefg > ####efg
abcdefgh > ####efgh
abcdefghi > #####fghi
abcdefghij > ######ghij
abcdefghijk > #######hijk
If the short hash is not required, then simply change the array as follows to get the other results:
def maskify(cc):
if len(cc) < 9:
split = [0,0,0,0,0,1,2,3,4][len(cc)]
else:
split = len(cc) - 4
return "#" * split + cc[split:]
Giving:
a > a
ab > ab
abc > abc
abcd > abcd
abcde > #bcde
abcdef > ##cdef
abcdefg > ###defg
abcdefgh > ####efgh
abcdefghi > #####fghi
abcdefghij > ######ghij
abcdefghijk > #######hijk
Upvotes: 1
Reputation: 55469
As others have mentioned #
starts a comment. If you want a string containing a hash you need to do '#'
.
As André Laszlo mentioned, Python strings are immutable, so it's impossible for a string operation to change a string's content. Thus the str.replace()
method can't change the original string: it needs to create a new string which is a modified version of the original string.
So if you do
cc = 'cat'
cc.replace('c', 'b')
then Python would create a new string containing 'bat'
which would get thrown away because you're not saving it anywhere.
Instead, you need to do something like
cc = 'cat'
cc = cc.replace('c', 'b')
This discards the original string object 'cat'
that was bound to the name cc
and binds the new string 'bat'
to it.
The best approach (AFAIK) to solving your problem is given in bebop's answer. Here's a slightly modified version of bebop's code, showing that it handles short strings (including the empty string) correctly.
def maskify(s) :
return '#' * (len(s) - 4) + s[-4:]
alpha = 'abcdefghij'
data = [alpha[:i] for i in range(len(alpha)+1)]
for s in data:
print((s, maskify(s)))
output
('', '')
('a', 'a')
('ab', 'ab')
('abc', 'abc')
('abcd', 'abcd')
('abcde', '#bcde')
('abcdef', '##cdef')
('abcdefg', '###defg')
('abcdefgh', '####efgh')
('abcdefghi', '#####fghi')
('abcdefghij', '######ghij')
Upvotes: 0
Reputation: 4813
The string literal '#' is not the same as the character # which starts an inline comment.
def maskify(cc):
cc = raw_input("Enter passcode: ")
mask = '#'*(len(cc)-4)
return mask + cc[-4:]
Upvotes: 0
Reputation: 8335
Just a little change to your own code:
cc = raw_input("Enter passcode: ")
n = len(cc)
c=""
for i in range(0, n-4): # i think a for loop would be good but i don't know how i'm going to use it yet
c+="#" #not entirely sure what to put here
cc= c+cc [-4:]
print cc
output:
Enter passcode: kased
#ased
Upvotes: 0
Reputation: 15537
The problem in the first example is that the #
is unquoted. You need to change it to '#'
otherwise it is parsed as the start of a comment and the enclosing parenthesis is a part of that comment. Although, this will only fix the parsing error.
The problem with strings is that you can't change characters inside of them (they are immutable). A common way to get around this is to create an array of the string, change the characters you want to change and then convert the array back to a string (often using ''.join(character_array)
). Try that!
Upvotes: 1