Python Forum
Help with function and sep( , ) value
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help with function and sep( , ) value
#1
Hi

Function def_length takes a list as a parameter and returns the length of the list. You must use a loop in your solution. You must not use built-in functions, list methods or string methods in your solution.

Function to_string(my_list, sep=', ') takes a list and a separator value as parameters and returns the string representation of the list (separated by the separator value) in the following form: item1, item2, item3, item4

The separator value must be a default argument.
i.e. sep=’1,1’

Given these parameters,my to_string function is giving an error UnboundLocalError: local variable 'entry' referenced before assignment as I am listing 'entry' inside and outside the loop ( I believe).

I have searched online and some solutions are telling me to make 'entry' Global. I don't know how to do this and also I don't think it's allowed within the rules anyway.

How can I iterate over my_list in the to_string () function and separate out the final entry of the list another way? (within the rules)

def length(my_list):

    loop_flag = True

    count = 0

    for entry in my_list:
        count += 1

    return count

 
def to_string(my_list, sep=', '):

    result = ''
    list_length = length(my_list)

    # Loop through indices except last
    for entry in range(list_length -1):
        result += my_list[entry] + sep
        
    # Add last item on
    result += my_list[entry + 1]

    return result
Reply
#2
How are you calling your function(s) when you receive the error? As is, your code appears to work correctly when given a list of strings as input:
Output:
>>> mystringlist = ['a','b','c','d'] >>> to_string(mystringlist) 'a, b, c, d'
It throws type errors for a list of anything other than strings, but that could be fixed by using the str() function when building your result in to_string(). (That appears to be within the rules the way I am reading them, as it only mentions not using built-in functions for the length() part of the assignment.)
Reply
#3
I was calling 3 lists to verify if the function was coded within the specs.

My file name was called list_function

import list_function

print("\nStart Testing!")

str_list1 = ['r', 'i', 'n', 'g', 'i', 'n', 'g']
str_list2 = ['r', 'e', 'd']
empty = []

print("\nlength Test")
print("List length:", list_function.length(str_list1))
print("List length:", list_function.length(empty))
The issue was that it gave this error when calling the last print function (empty)

Error:
File line 24, in <module> print("List is:", list_function.to_string(empty)) File line 24, in to_string result += my_list[entry + 1] UnboundLocalError: local variable 'entry' referenced before assignment
This was solved by adding the line

if not my_list: 
    return result
Is this a clean way of doing things to account for the empty print function?

def length(my_list):

    loop_flag = True

    count = 0

    for entry in my_list:
        count += 1

    return count

 
def to_string(my_list, sep=', '):

    result = ''
    list_length = length(my_list)

    if not my_list:
        return result

    # Loop through indices except last entry.
    for entry in range(list_length -1):
        result += my_list[entry] + sep
        
    # Add last entry on.
    result += my_list[entry + 1]

    return result
Reply
#4
Aha! When I was testing your functions I did not try an empty list, but now this makes sense. Your for loop would not execute with list_length having a value of 0, so the variable "entry" had not been assigned a value when you reached the "Add last entry" part of the code.

Yes, I think your way of handling the empty list is simple and works effectively. Are you expected to account for any scenarios other than a valid list of stings and an empty list? If not, it looks like you are done.

One thing... It doesn't appear that you ever use your loop_flag variable, so you should be able to get rid of line 3.
Reply
#5
Thanks mate. No that's all the scenarios covered. Yes good pickup, that is just a random line there that I thought I needed to do something with earlier but had left in by mistake.

While I have you... do you know what is wrong with this?

def insert_value works perfect.

def_remove_value does not.

I know I shouldn't have the empty = '' there as that actually puts '' into the index but other than that it seems like it should just be the flipping of my insert_value function, which is the only function working as intended right now.

There are a couple of rules again... You must use a loop in your solution. You may make use of the list_name.append(item) method in order to build the new list. You must not use built-in functions (other than the range() function), slice expressions, list methods (other than the append() method) or string methods in your solution.

What I'm calling is this:

print("\ninsert_value Test")
str_list3 = ['one','three','four', 'five', 'six']
new_list = list_function.insert_value(str_list3, 'two', 1)
print(new_list)
str_list4 = ['i', 't']
str_list4 = list_function.insert_value(str_list4, 'p', 0)
print(str_list4)
str_list4 = list_function.insert_value(str_list4, 's', -1)
print(str_list4)
str_list4 = list_function.insert_value(str_list4, 's', 7)
print(str_list4)

print("\nremove_value Test")
str_list5 = ['r','i','n','g']
new_list = list_function.remove_value(str_list5, 2)
print(new_list)
new_list = list_function.remove_value(str_list5, -1)
print(new_list)
new_list = list_function.remove_value(str_list5, 10)
print(new_list)
def insert_value(my_list, value, insert_position):

    new_list = []
    list_length = length(my_list)
    list_index = 0
    value_position = insert_position

    #if insert pos is not valid 
    if insert_position <= 0:
        value_position = 0
    elif insert_position > list_length - 1:
        value_position = list_length

    while list_index < list_length:
        if list_index == value_position:
            new_list.append(value)
        new_list.append(my_list[list_index])
        list_index += 1

    if value_position == list_length:
        new_list.append(value)
                
    return new_list

# Function remove_value() - place your own comments here...  : )
def remove_value(my_list, remove_position):

    new_list = []
    list_length = length(my_list)
    list_index = 0
    value_position = remove_position
    empty = ''

    if remove_position <= 0:
        value_position = 0
    elif remove_position > list_length -1:
        value_position = list_length

    while list_index < list_length:
        if list_index == value_position:
            new_list.append(empty)
        new_list.append(my_list[list_index])
        list_index += 1

    if value_position == list_length:
        new_list.append(empty)
        
    return new_list

Final part is this:

7. Write a function called reverse(my_list, number=-1) that takes a list and a number as parameters. The function returns a copy of the list with the first number of items reversed.

Again there are rules:

The number parameter must be a default argument.
- If the default argument for number is given in the function call, only the first number of items are reversed.
- If the default argument for number is not provided in the function call, then the entire list is reversed. Check for the number value exceeding the list bounds (i.e. is greater than the length of the list).
- If the number value exceeds the list bounds, then make the number value the length of the list.
- If the number value entered is less than two, then return a copy of the list with no items reversed.

I will get stuck on this for sure and be posting more jumbled up code that I would like a hint of two on :D
Reply
#6
What is remove_value supposed to do? You have only told us about insert_value and to_string
pyzyx3qwerty
"The greatest glory in living lies not in never falling, but in rising every time we fall." - Nelson Mandela
Need help on the forum? Visit help @ python forum
For learning more and more about python, visit Python docs
Reply
#7
Yea soz

remove_value(my_list, remove_position) takes a list and a remove_position as parameters. The function returns a copy of the list with the item at the index specified by remove_position, removed from the list.

I will be using the earlier def length(my_list): function throughout to initialise list_length as length(my_list)
Reply
#8
(Jun-01-2020, 12:00 PM)drewbty Wrote: def insert_value works perfect.

def_remove_value does not.

I know I shouldn't have the empty = '' there as that actually puts '' into the index

You have correctly identified your problem. You are using new_list.append(empty), which adds the value of empty to the list, when what you really want to do here is nothing at all and then move on to the next index. Take another look at it and find a way to accomplish that. Just keep in mind that you don't need to add anything when you get to the remove_position, you just want to bypass it.

Also, when you are given an index out of range like in the line below, do you actually want to remove the last index or do you want to just ignore this? (I'm genuinely not certain what you want here.) Adjust your code according to your desired outcome.
new_list = list_function.remove_value(str_list5, 10)
*Edit* - One other possible issue is that for a value less than 0 you are changing the index (value_position variable) to 0. Is that really what you want to do?
Reply
#9
The following rules apply to insert_value() and remove_value()

Check for the insert_position value exceeding the list (my_list) bounds.
- If the insert_position is greater than the length of the list, insert the value at the end of the list.
- If the insert_position is less than or equal to zero, insert the value at the start of the list.

Check for the remove-position value exceeding the list (my_list) bounds.
- If the remove_position is greater than the length of the list, remove the item at the end of the list.
- If the remove_position is less than or equal to zero, remove the item stored at the start of the list.

The following rules apply to reverse()

The number parameter must be a default argument.
- If the default argument for number is given in the function call, only the first number of items are reversed.
- If the default argument for number is not provided in the function call, then the entire list is reversed. Check for the number value exceeding the list bounds (i.e. is greater than the length of the list).
- If the number value exceeds the list bounds, then make the number value the length of the list.
- If the number value entered is less than two, then return a copy of the list with no items reversed.


I'm had a good crack at the remove and reverse functions and I think I fully understand what I'm trying to do, I just lack the python knowledge to implement it.

e.g. here I have 'pass' in the remove function and .reverse in the reverse function I know isn't right (and not allowed under the rules of only being able to use append and range anyhow)

def insert_value(my_list, value, insert_position):

    new_list = []
    list_length = length(my_list)
    list_index = 0
    value_position = insert_position

    #if insert position is not valid.
    if insert_position <= 0:
        value_position = 0
    elif insert_position > list_length - 1:
        value_position = list_length

    while list_index < list_length:
        if list_index == value_position:
            new_list.append(value)
        new_list.append(my_list[list_index])
        list_index += 1

    if value_position == list_length:
        new_list.append(value)
                
    return new_list

def remove_value(my_list, remove_position):

    new_list = []
    list_length = length(my_list)
    list_index = 0
    value_position = remove_position

    #if remove position is not valid. 
    if remove_position <= 0:
        value_position = 0
    elif remove_position > list_length -1:
        value_position = list_length

    #iterate through the list_length
    while list_index < list_length:
        # remove/pass once iteration lands on the value position
        if list_index == value_position:
            pass
        new_list.append(my_list[list_index])
        list_index += 1

    # if at the end of the list, also remove/pass
    if value_position == list_length:
        pass
        
    return new_list

def reverse(my_list, number=-1):
    
    new_list = []
    list_length = length(my_list)
    list_index = 0
    reverse_pos = number


    #if number value entered is less than 2, return copy of list (nothing reversed)
    if reverse_pos <= 1:
        my_list = new_list
    #if no number given, use the default value of -1
    elif reverse_pos == -1:
        reverse_pos = -1
    #if the position exceeds list length, make the reverse pos to be the length of the list. 
    elif reverse_pos > list_length -1:
        reverse_pos = list_length -1

    while list_index < list_length:
        #iterate through and once we reach the reverse_pos
        if list_index == reverse_pos:
            #reverse my_list at that point from the range of 0:reverse_pos
            new_list.reverse(my_list[0:list_index])
            #append all values onto the new_list
            new_list.append(my_list[list_index])
                if list_index > reverse_pos:
                #append all values onto the new_list
                new_list.append(my_list[list_index])
        new_list.append(my_list[list_index])
        list_index += 1

    return new_list
I'm using this to call in my file name called list_function.py

print("\ninsert_value Test")
str_list3 = ['one','three','four', 'five', 'six']
new_list = list_function.insert_value(str_list3, 'two', 1)
print(new_list)
str_list4 = ['i', 't']
str_list4 = list_function.insert_value(str_list4, 'p', 0)
print(str_list4)
str_list4 = list_function.insert_value(str_list4, 's', -1)
print(str_list4)
str_list4 = list_function.insert_value(str_list4, 's', 7)
print(str_list4)

print("\nremove_value Test")
str_list5 = ['r','i','n','g']
new_list = list_function.remove_value(str_list5, 2)
print(new_list)
new_list = list_function.remove_value(str_list5, -1)
print(new_list)
new_list = list_function.remove_value(str_list5, 10)
print(new_list)

print("\nreverse Test")
str_list6 = ['e', 'd', 'u', 'd']
str_list7 = ['m', 'o', 'b', 'b', 'e', 'd']
new_list = list_function.reverse(str_list6, 4)
print(new_list)
new_list = list_function.reverse(str_list7, 3)
print(new_list)
new_list = list_function.reverse(str_list6)
print(new_list)
Reply
#10
I've figured out the remove position (now solved) and thrown all dices are the reverse function but no joy.
The line element -= 1 is not valid ( I want to reverse from this point). Any help would be appreciated to tidy this up.

def remove_value(my_list, remove_position):

    new_list = []
    list_length = length(my_list)
    list_index = 0
    value_position = remove_position

    #if remove position is not valid. 
    if remove_position <= 0:
        value_position = 0
    elif remove_position > list_length -1:
        value_position = list_length -1

    #iterate through the range of my_list
    while list_index < list_length:
        # only append to new_list when the list_index doesn't land on the value_position
        if list_index != value_position:
            new_list.append(my_list[list_index])
        list_index += 1
              
    return new_list

def reverse(my_list, number=-1):
    
    new_list = []
    list_length = length(my_list)
    list_index = 0
    reverse_pos = number


    #if number value entered is less than 2, return copy of list (nothing reversed)
    if reverse_pos == -1:
        reverse_pos = -1
    elif reverse_pos <= 1:
        my_list = new_list
    #if the position exceeds list length, make the reverse pos to be the length of the list. 
    elif reverse_pos > list_length -1:
        reverse_pos = list_length -1
    else:
        reverse_pos = number

    while list_index < list_length:
        #iterate through and once we reach the reverse_pos
        for element in my_list:
            if list_index == reverse_pos:
                new_list.append(my_list[list_index])
                element -= 1
            elif list_index != reverse_pos:
                new_list.append(my_list[list_index])
                element += 1
        list_index += 1

    return new_list
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020