How does python know to use our word with range()?

I must be forgetting something but how does python know to use “word” when iterating through “i” through the range() defined? What if we had a second variable in the function and wanted to use the range defined to iterate through that second variable and not “word”? How do you define what variable you want to the range() to refer to if there is more than one?

def every_other_letter(word):
every_second_letter =“”
for letter in range(0, len(word), 2):
every_second_letter += word[letter]
return every_second_letter

3 Likes

range() just returns a sequence of integers, assigned each time to an iterator variable. It is up to you to define how to use the variable. It can be used as an index, or simply as an int

str1 = "abc"
str2 = "123"
out_str = ""
count = 0
for i in range(len(str1)):
    out_str += str1[i] * int(str2[i])    # i is an index to two different strings
    count += i        # i is an integer used in counting
print(out_str, count)

Output;

abbccc 3
3 Likes

ahh. Pretty simple when you put it that way :-). Thanks

1 Like

Wait, why is there a *? The way I see your code you’re trying to multipli str by str which is impossible so what am I missing?

1 Like

clearly not since the right side is an int instance

that’s what I’ve been saying once or twice elsewhere, you need to find out what things are

consider where they were defined and what operations were involved, you should be accounting for the types everywhere, the type is the first thing you need to know about a value that you’re going to do something with.
and if you’re not sure or want to verify, you can print the type, but, due to also needing what should happen, that also says a whole lot about what different things are, so you should probably know anyway.

maybe you’d start out with a string, and you’d split it, now you’d have a list of strings, maybe you’d then concatenate them again, you’d now have a string again, maybe you want the length, now you have an int, what would you do with the int? maybe you want to combine an int with "*" to produce an equally long string, so now you would need some kind of replicate operation between string and int. does that exist? maybe, otherwise make it, doesn’t really matter, what matters is that you are keeping an iron grip on what’s what and what’s being done.

a program is a whole lot of combining and transforming values and it’s up to the programmer to make sure that the different parts fit together, the programmer needs to very intentionally decide things like hey look I have an integer and a list of things, I would like to have many lists, each with a size equal to that integer, and then go implement that relation, come back and continue with the next thing

def chunks_of(n, xs):
    xs = iter(xs)
    while True:
        out = [x for _, x in zip(range(n), xs)]
        if not out:
            break
        yield out
>>> list(chunks_of(3, range(20)))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14], [15, 16, 17], [18, 19]]

Now you’d have a list of numbers what would you want with that? That would be yet another operation for which to consider what inputs there are and what output is desired.

You would very rarely make a U-turn on something you’ve implemented because what you’ve written is something you’ve decided need to happen, and then you would move forward from there.

print(type(str1[0]))
print(type(int(str2[0])))

gives me

<class 'str>
<class 'int>

so therefore that’s not the case

Yes, your previous post made me realize that. Still I don’t know how is it possible to multiply string by integer, especially since string contains only letters so how is a methematical operation can be done on that?

Operators are implemented by their left operand. (or the right if the left one doesn’t implement it)
You’re asking the string to multiply my some number.

If you have five times “hello” what do you get? Presumably “hello”“hello”“hello”“hello”“hello”, but if you multiply a string then you’d probably want a string back (a list would make sense too, but a bit less because list wasn’t part of the operands and usually for multiplication the type of the result is based on the operands)
so the two possible sensible results would then be:

"hellohellohellohellohello"
["hello", "hello", "hello", "hello", "hello"]
class ThisCanBeMultiplied:
    def __mul__(self, other):
        # don't do anything, just return the operands
        return (self, other)


myobj = ThisCanBeMultiplied()
result = myobj * 100
print(result)
(<__main__.ThisCanBeMultiplied object at 0x7f6ab80ed6d0>, 100)
        ^ the object itself ^            the other operand ^

So the real question then is whether str promises to have this behaviour.

It’s not particularly important whether it does, because you should already have decided that you want this behavior, and because you know your inputs and outputs, you can describe the action you need, you can go googling for how to implement this or whether it exists in some form or just implement it yourself without any googling

2 Likes

Oh, nice, I didn’t know we can just multiply strings like that. I wrote it down to make sure I remember it.

No don’t remember it. Don’t remember a bunch of specific things.
Decide on an action and then go find out or implement it.

What you mainly need to remember is what the different types ARE. When you know what something is you can reason about what makes sense to do with them. And then you can make decisions about what you want to do. And when you’ve decided, you can start considering how to carry it out, you can research it.

A string is a series of characters.

Can you have several strings and concatenate them? Yeah, duh. And that’s what multiplying a string and int does, but the fact that it is possible to carry out this action, that comes from considering what you have and what you need, it does not come from knowing a bunch of specific operations.

3 Likes

I meant that i wrote down that I can multiply strings. I cannot think about an action if in my head this action is impossible.

the fact that it is possible to carry out this action, that comes from considering what you have and what you need,

Maybe for a programmer it does, when you already know stuff. But if in my mind str cannot be multiplied by int I won’t ever consider it.

A lot of times I know what I want my code to do but I don’t know what syntax to use and like you said, that’s when it’s time for research. Like in this example, thanks to google I found out that I can solve this like this:

def reverse_string(word):
 return word[::-1]

But I want to be able to come up with those ideas by myself, not research every time, this is why I’m writing some things down, because this way they become mine, I can consider them because I know about them.

Is it impossible to copy a string some amount of times and then concatenate those copies?
It is completely irrelevant how that is written, that’s not something you need to know to reason about it. That’s my whole point. Ignore the code, decide what to do.

By being human you already have the reasoning skills required to manipulate information. That’s where all your decisions need to happen.
When you then implement it you need to stick to those decisions, not randomly try stuff.

That’s not an idea though is it, that’s just using an already existing solution, avoiding implementing it.
If you want to implement reverse, then the ideas that go into that is stepping through the list backwards and adding them to a new list, and then once the order is done, concatenate everything you put in that list to obtain the new reversed string. By knowing the basic characteristics of a string, that is something you can come up with. You know it’s got an index for each character, you know that you can do repetition with a loop, you know that you can count by adding 1 or count down by subtracting 1… so if you stop looking for some magical finished solution and instead look at the basic things … all the big complicated things are just some composition of smaller more basic things, so use the basic things instead. Don’t stop in despair just because you don’t know some magical already existing solution. If you need some subaction, go implement it and then use what you implemented to write what you initially wanted.

And no you’re not supposed to not research. You’re supposed to have your nose in the documentation pretty much all the time because there are lots of things that you need to use and you need to now how they behave to make use of them. When you’ve decided what you’re doing you’re on a mission to find things that you can use to describe what you decided. You’re certainly not going to figure out clever things without researching how to do things, but it’s not clever things you’re looking for, it’s basic things that you can use to build your own clever things.

Regarding reversing a string, you might also guess that reversing might be a basic behaviour that a string supports. How do you write that? You’d google it or look in documentation if you know where. Because you’ve decided what you’re looking for. You don’t magically know that you can use slicing to ask a string to reverse. You instead say “hey maybe string supports this, seems like a thing it might implement” and then you go check whether it does and how to make that request to it.

You’ll find clever tricks and pick them up over time simply by observing what you have and what you want and from that deducing what action you need. Then you’d go looking for that action.

5 Likes

In this problem we just need to know the length of the variable word with the sequence operator len(), to apply to our range constructor. Ranges .

This is a easy manner to resolve this problem and I would like other coders could see it too.

def every_other_letter(word):
  string = ''  
  for i in range(0,len(word),2):         #A range with a step of two
    for s in word[i]:                            # Obtaining every letter in word by it's index                                                
      string += s
  return string


print(every_other_letter("I love code"))
# should pint Ilv oe
1 Like

I was using range and len; but I did not remember range could do the steps.

After looking at the solution, I was still sure that there had to be a way to get this done without using the “steps” in range. With a condition and the length of the word.

This is what I came up with:
def every_other_letter(word):

every_other = “”

for i in range(len(word)):

if i*2 < len(word):

  every_other += word[i*2]

return every_other

Note that word[i] is a string composed of a single character only. So iterating a single-character string using an iterative statement (for-loop or while-loop) is worthless.

Also, string is a module or library in Python. So, variable or function names should avoid such naming as much as possible to prevent confusion. (More preferrable to use strng) So, the code above should be simplified to:

def every_other_letter(word):
  strng = ''  
  for i in range(0,len(word),2):         #A range with a step of two                                     
      strng += word[i]
  return strng

Please don’t revive old topics.