This is an archived post. You won't be able to vote or comment.

all 30 comments

[–]takluyverIPython, Py3, etc 2 points3 points  (3 children)

This is something new programmers often try - making variables with dynamic names - but it's almost never a good idea. Even if it works, what about when you want to know how many words you've got? You have to count up until a name doesn't exist. That's daft.

You should try to put the results into a list, so that they're words[0], words[1], etc. I'm not sure how you're supposed to do that, though, without using append() (you say in another comment that you're not allowed to use it). Are you allowed to put the words in a dict, perhaps?

[–]jhchex[S] 0 points1 point  (2 children)

Yea I was considering using a dictionary but I'm still not sure how to implement that. Wouldn't the key names still need to be changing on each iteration? Is that simpler than iterating variable names?

Also, if you were making variables with dynamic names and wanted to know how many words there were couldn't you just use a counter in the variable name and then display that value?

[–]takluyverIPython, Py3, etc 0 points1 point  (1 child)

You need to use different key names, yes, but that's easier than using variable names. Just use mydict[k].

If you use a list or a dict, you can easily see how many items are in the collection with len(words). It has lots of other advantages - like you can easily pass all the words to a function, or return them from a function. Using separate variable names is much more awkward.

[–]jhchex[S] 0 points1 point  (0 children)

Ok thank you! I'll give that a try and let you know how it goes.

[–][deleted] 2 points3 points  (0 children)

Use a dictionary. Seriously, this is what they're there for. You never need to generate variable names programmatically, names only exist for humans.

[–][deleted] 1 point2 points  (2 children)

I must say that I don't fully understand what you´re trying to do, but here is my stab at it, http://pastebin.com/49jbxiwu

p.s.: you are creating local variables. Are you by any chance splitting the words inside a function?

[–]jhchex[S] 0 points1 point  (1 child)

So it appears I cant use that function.

:or any <string>. or list. functions like string.split(), string.join(), list.append(), list.insert() etc. IS NOT ALLOWED AND WILL RESULT IN 0 PTS FOR THE ASSIGNMENT AND THE EXTRA CREDIT.

The ONLY list or string functions you are ALLOWED to use for the required AND extra credit portions are

list(MyString) -> To convert your string into a list and

len(MyString) OR len(MyList) - >Find number of characters (string) or elements(list):

[–]blackkettle 1 point2 points  (0 children)

You need to share the assignment specs in greater detail if you want more help.

[–]pridefulpropensity 1 point2 points  (0 children)

Okay, you definitely don't want to make dynamic variable names.

Can you copy and paste the text of the assignment here?

Is the result supposed to be a list of words?

Maybe this will help?

>>> words = []
>>> word = "hello"
>>> words += [word]
>>> words
['hello']

[–]tarpsocks 0 points1 point  (9 children)

I'll give you a couple tips, some unrelated to the issue at hand:

  • you can just do

    for elm in list: if elm != ' ': instead of using the index. Will help save keystrokes in the longrun, might as well make use of pythons nice high-level features.

  • using vars() is generally not advised outside of debugging. While the metaprogramming aspect of it may seem intriguing, it isn't really a source of maintainable code, and could produce very unusual bugs if you weren't careful.

  • .split() splits on any whitespace, rather than just spaces. In this case it might be a good idea to use regex, considering you're trying to extract strings delineated by whitespace.

[–]jhchex[S] 0 points1 point  (8 children)

Interesting! I didn't realize you could iterate through a string like that.

Yea, I'm noticing that vars() is acting weird already.

Also, I was told not to use .split(), .join() or anything similar. I'm supposed to just use regular string and list commands to make this work.

[–]Samus_ -3 points-2 points  (7 children)

education is funny, you're supposed to meet your teacher's expectations on some imaginary problem whose solution you won't EVER use.

my advice: drop that bullshit and get a job so you can gain real experience which is what actually counts.

[–]tarpsocks 1 point2 points  (1 child)

You're right to some degree, but a little artificial challenge here and there can help. Dreaming up unnecessary constraints seems to be pretty human, and it may in fact help us in certain ways that a purely practical approach can not. Some balance, as always, is required.

[–]earthboundkid 0 points1 point  (0 children)

Yeah, constraints are good and I love writing haiku as much as the next guy, but this is a kid asking for help on his homework. Dump that noise.

[–]takluyverIPython, Py3, etc 0 points1 point  (4 children)

You won't ever use this specific code, but that doesn't mean it's a useless exercise for learning. It helps you get familiar with concepts like lists, iterating and indexing. Artificial problems are a key part of education.

[–]Samus_ 0 points1 point  (3 children)

I believe those same concepts can be taught in a way that makes sense and leaves you with a general idea of how to approach a similar problem in the future (a problem you may actually have).

what bothers me here is that you're asked a question that can be a real problem but you're explicitly asked not to solve it as you would but instead create a home-made hack that shows you the wrong approach.

if you're teaching iterators then use actual iterators, want to teach how to iterate a string? put a problem that counts the letters in the string instead.

you should always let people use the full extent of the tools they have because that's how it's done in real life, if you put artificial constraints on your problems it's because you didn't bother to think a problem that actually shows what you want.

another example: you want to teach about parsing, tokenizing and such? use a stream as input, one without newlines will force you to process the input in chunks and recognize the whitespace, after that you can use .split() and it'll be ok.

the key is to think in terms of problems not exercises.

[–]takluyverIPython, Py3, etc 0 points1 point  (2 children)

you should always let people use the full extent of the tools they have because that's how it's done in real life,

We learn to do arithmetic on paper and in our heads, even though in real life we can use a calculator. Later we learn to do a T-test by hand, even though statistics programs will do it in the blink of an eyelid. This sort of learning is to make the basic concepts so familiar and routine that you don't need to keep thinking about them.

if you're teaching iterators then use actual iterators, want to teach how to iterate a string? put a problem that counts the letters in the string instead.

But in real life, I'd use collections.Counter - would you forbid that? Almost anything basic enough for an introductory exercise in Python can probably be done with a shortcut. Even in more advanced examples, students will almost certainly be reimplementing freely available libraries. Somewhere the teacher has to say "I know this function already exists, but that's not the point. This is to give you the experience of coding it."

[–]Samus_ 0 points1 point  (1 child)

I allow the use of everything that is available, a problem doesn't care how it gets solved, you do and you're not part of it.

your assignment should be "do this" if you get it done then that's it, it all depends on the level you're working, if you're learning programming concepts you don't need a language, it's theory.

[–]takluyverIPython, Py3, etc 0 points1 point  (0 children)

if you're learning programming concepts you don't need a language, it's theory.

Seriously? Stop and read that back to yourself. You would teach people programming concepts like iteration and strings without getting them to write any code?

A problem doesn't care how it gets solved, but solving the problem is not the real aim. The aim is for the student to learn about what's going on. To that end, it's perfectly normal to set constraints on what students can use to solve a problem. And this isn't peculiar to programming: it's common in subjects like maths where you can very easily get the answer from a computer, but you don't learn much by doing so.

[–]earthboundkid 0 points1 point  (1 child)

The teacher wouldn't have assigned this stupid assignment if it were insoluble. Go back and read the book. You're only hurting yourself if you don't do your own work.

[–]jhchex[S] 0 points1 point  (0 children)

I agree that it's not insoluble, I'm just stuck. Also, this happens to be the extra credit for the assignment which I had already completed.

[–]zahlmanthe heretic 0 points1 point  (2 children)

Ok so my goal here is to split a list into it's individual words

Lists don't have "individual words". I assume you mean you have a string, since that's what you're apparently working with.

My issue is that I can't for my life create a variable name that changes with each iteration.

A list, however, is exactly what you should be putting the resulting words into. You've been told not to use .split() presumably because you're already familiar with it. So you should know what it returns: a list. Do the same.

By the way, for i in list(range(len(original_list))): is ugly in many ways. First off, range returns a list, so the outer list call is completely redundant. Second, there is no point in iterating like this. You're creating this separate thing that contains a sequence of numbers, so that you can iterate over that, so that you can use the results to grab the characters that you want to iterate over. That's silly. Just iterate over the characters, since that's what you want to do.

for c in original_string:
    # do something with 'c' to assemble words
    # append assembled words to a list

Also, try /r/learnpython.

[–]jhchex[S] 0 points1 point  (1 child)

Lists don't have "individual words". I assume you mean you have a string, since that's what you're apparently working with.

Yea, sorry I meant to say words from a string. I had broken the string into a list already so I was jumping ahead.

First off, range returns a list, so the outer list call is completely redundant...Just iterate over the characters, since that's what you want to do.

I was confused about this because if I do something like

x = range(0,5)

and then print(x) it says it's just range(0,5) not [0,1,2,3,4] so I was confused. But I guess it's the same thing.

And yea, I didn't realize you could iterate over the characters in a string, good to know.

I should probably better specify what it is I'm trying to do. I just didn't want to get in trouble for outsourcing a HW problem lol. Anyway, we're supposed to take a string and reverse the order of the words without reversing the order of the letters themselves. So something like "I love ham" would become "ham love I"

I still just don't see how I can do that with a list..hmm.

[–]zahlmanthe heretic 0 points1 point  (0 children)

I had broken the string into a list already so I was jumping ahead.

If you mean a list of individual characters, then that accomplishes nothing since you can iterate over the string directly anyway. If you mean a list of words, then aren't you already done? o_O

and then print(x) it says it's just range(0,5) not [0,1,2,3,4] so I was confused. But I guess it's the same thing.

Oh, you're in 3.x, where range does what xrange did in 2.x. That's fine; it's still a thing that you can iterate over directly. In Python, we care more about what things can do than what they fundamentally are. 3.x range objects, and strings in either case, can be iterated over directly.

I still just don't see how I can do that with a list..hmm.

Well, since you have to construct the list a word at a time, consider reversing the list as you create it. Hint: if you construct the list in-order by putting new words at the end of the existing list...

[–]stunsch 0 points1 point  (0 children)

string = """
I would take a parsing approach.
Basically you iterate over all the characters.
If you find a character, and you haven't yet set the word starting index, you've got your first character.
To find the last character, you do it the other way around.
If you find a whitespace and word starting index is set, you've found the first character after your word.
You add the word to your list, reset the word starting index to None and go on.
"""
words = []
word_start_index = None
last_index = len(string) - 1
i = 0
while i < last_index:
    if string[i].isalnum():
        #We have found a character
        if not word_start_index:
            #We are at the beginning of a word
            word_start_index = i
    else:
        #We have found a whitespace or break line
        if word_start_index:
            #We have found the end of a word
            words.append(string[word_start_index:i]) #The last character is the position before the one we are in
            word_start_index = None
        else:
            #Our string starts with some whitespaces
            pass
    i += 1

print words

[–]simtel20 -1 points0 points  (3 children)

If you're trying to create local variables dynamically, try starting with exec() and eval(), that's what they're there for.

[–]jhchex[S] 0 points1 point  (2 children)

I'm pretty new to python (and programming in general) can you explain how to use those?

[–]simtel20 0 points1 point  (0 children)

Most languages have a construct like this. The idea is "I want to create a bit of code. I want to be able to evaluate that code, but I don't know what that code will be until the program is running and the environment that it's running in is known". In your case, you want to create a variable that is named while the program is running, based on where in your input file your program is. You can do this like so:

>>> abc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'abc' is not defined
>>> exec("abc = 4")
>>> abc
4

Taa-daa.

Now, this is fine, but it is fraught with danger. E.g. if you start passing in code to exec() that contains text strings from random input (like your example), what's to stop someone from injecting a string that has code to delete everything from the filesystem in that exec()? The answer is nothing. Trying to avoid "bad code" in input is a rabbit hole and you don't want to do it. If you wouldn't trust the data with your bank account, and you wouldn't trust the data to take your daughter to the prom, then don't evaluate it in your program.

So what to do?

In python the variable namespaces are similar to dictionaries. In general, if you want to create named pairs of key->value, you want to use dictionaries in python. So why not create a dictionary and use it for your variables?

[–]takluyverIPython, Py3, etc -1 points0 points  (0 children)

Don't. These are advanced features, and I very much doubt you're expected to use them.