function calling by rigid python keyword - python

why list object is not callable inside a function ??
CODE:
def unique_list(list1):
sets=set(list1)
u_list=(list(sets))
print("old list",list1)
print('unique list',u_list)
list1=[1,1,2,3,4,4,5]
unique_list(list1)
when i did this.. I got the exact output [1,2,3,4,5]... BUT
if i use list in lieu of list1 or any other name like the following code:
def unique_list(list):
sets=set(list)
u_list=(list(sets))
print("old list",list)``
print('unique list',u_list)
list=[1,1,2,3,4,4,5]
unique_list(list)
python throws error:
TypeError: 'list' object is not callable
is it for this reason that rigid keywords must not be used as variable name ?? or for other reasons ??

Heres working code for what you want to do
def unique_list(list1):
print("old list",list1)
print('unique list',(list(set(list1))))
list1=[1,1,2,3,4,4,5]
unique_list(list1)
here's why your code wasn't working
lets take a look at the code that defines your function
def unique_list(list):
#code
list is a class name and list() is a function that is native to python; by making it a parameter and or variable, you are overriding it!
So, when you call list(set(list)) its basically saying: parameter(set(parameter))
Obviously the parameter cant be a function and a list at the same time; so there isn't any scenario where this could work.
I recommend using convention names like so if you arent sure what to call a list:
lst = []
x = []
l = []
The only time you should ever put any of these names alone into the definition of a function is through type-hinting
def foo(s: str, l: list) -> list:
#do code
return l + list(s)
In conclusion... it's a horrible practice to use any built-in function/class names in python as variable/functions unless you are actually trying to override them.

Related

Can you call/use a function returned from a list in Python?

I'm trying to store a function in a list, retrieve the function from the list later, and then call on that function. This is basically what I want to do, without any specifics. It doesn't show my purpose, but it's the same issue.
elements: list = [] # List meant to contain a tuple with the name of the item and the function of the item.
def quit_code():
exit()
element.append(("quit", quit_code))
Now, somewhere else in the code, I want to be able to use an if statement to check the name of the item and, if it's the right one at that time, run the function.
user_input = "quit" # For brevity, I'm just writing this. Let's just imagine the user actually typed this.
if elements[0][0] == user_input:
#This is the part I don't understand so I'm just going to make up some syntax.
run_method(elements[0][1])
The method run_method that I arbitrarily made is the issue. I need a way to run the method returned by elements[0][1], which is the quit_code method. I don't need an alternative solution to this example because I just made it up to display what I want to do. If I have a function or object that contains a function, how can I run that function.
(In the most simplified way I can word it) If I have object_a (for me it's a tuple) that contains str_1 and fun_b, how can I run fun_b from the object.
To expand on this a little more, the reason I can't just directly call the function is because in my program, the function gets put into the tuple via user input and is created locally and then stored in the tuple.
__list_of_stuff: list = []
def add_to_list(name, function):
__list_of_stuff.append((name, function))
And then somewhere else
def example_init_method():
def stop_code():
exit()
add_to_list("QUIT", stop_code())
Now notice that I can't access the stop_code method anywhere else in the code unless I use it through the __list_of_stuff object.
Finally, It would be nice to not have to make a function for the input. By this, I mean directly inserting code into the parameter without creating a local function like stop_code. I don't know how to do this though.
Python treats functions as first-class citizens. As such, you can do things like:
def some_function():
# do something
pass
x = some_function
x()
Since you are storing functions and binding each function with a word (key), the best approach would be a dictionary. Your example could be like this:
def quit_code():
exit()
operations = dict(quit=quit_code)
operations['quit']()
A dictionary relates a value with a key. The only rule is the key must be immutable. That means numbers, strings, tuples and other immutable objects.
To create a dictionary, you can use { and }. And to get a value by its key, use [ and ]:
my_dictionary = { 'a' : 1, 'b' : 10 }
print(my_dictionary['a']) # It will print 1
You can also create a dictionary with dict, like so:
my_dictionary = dict(a=1, b=10)
However this only works for string keys.
But considering you are using quit_code to encapsulate the exit call, why not using exit directly?
operations = dict(quit=exit)
operations['quit']()
If dictionaries aren't an option, you could still use lists and tuples:
operations = [('quit',exit)]
for key, fun in operations:
if key == 'quit':
fun()

Module with text files

I am very new to python, and am writing a code with multiple modules.
Each of my modules manipulates the same list that I have named "myList", however, I am having trouble understanding how to get the list into each module.
For example, one module called reverseList.py needs to take the list and reverse it, but when it is run in my main function, I get an error that the list does not exist.
Import reverseList
def main():
with open('list3.txt', 'r') as f:
data = f.read()
data = data.split("\n")
myList = [row.split(",") for row in data]
reverseList.reverse()
NameError: name 'myList' is not defined
The reverseList.py module is as follows:
def reverse()
myList1 = myList[::-1]
print(myList1)
return
It is unclear where exactly the error comes out since you didn't include your entire main function - there is no place myList is used before/after its definition. But I can think of a couple of reasons for the error.
The error shows up when a variable is used before it is defined. So, you might have the variable myList before you define it in line 4 of your current code.
In python, indentation is the matter of correctness of your code. Meaning, line 2~4 should be indented if you didn't do so.
I might be able to come up with a better answer if you present the rest part of the code.
Your update reveals where the problem is happening; that is from your reverseList, not your main.
You are loading myList in reverseList, but it has never been defined. myList defined in main is not accessible from reverseList. To fix this problem, you should pass myList as an argument to the function reverse when it is called and use that in your reverse function.
main:
reverseList.reverse(myList)
reverseList:
def reverse(myList):
myList1 = myList[::-1]
print(myList1)
return
Note that the argument name of the function reverse can be different from the one in main. In other words, it doesn't matter if you do follow;
def reverse(myList2):
myList1 = myList2[::-1]
print(myList1)
return
This might be better:
def reverse(myList2):
print(myList2[::-1])

TypeError: 'function' object is not iterable' Python 3

I'm trying to write a program that will open a text file from the web consisting of 10,000 words, then 'clean' the file to get rid of nonsense words, such as 'aa'. I eventually want to use these words to do other things so I want to add the non 'non-sense' words to be put into a new list. Every time i try to run this I run into the error code TypeError: 'function' object is not iterable.
import urllib.request
def readWordList():
response = urllib.request.urlopen("http://www.mit.edu/~ecprice/wordlist.10000")
html = response.read()
data = html.decode('utf-8').split()
return data
clean = readWordList()
def clean(aList):
newList = []
for word in aList:
if range(len(word)) >= 2:
newList.append(word)
return newList
clean(clean)
Make up your mind: is clean supposed to be a list or a function? You started as a list, but then replaced that with a function, and then told the function to clean itself. Try this:
dirty_list = readWordList()
def clean(aList):
...
clean(dirty_list)
You create a variable called clean, immediately overwrite the name by declaring a function with the same name, then pass the function clean to itself.
Either change the function name, or the variable above with the same name.
Firstly you make a variable called clean and then you make a function called clean and finally you tried to use the function in the variable, both called clean. You "destroy" the variable when you defined a function. They must have different names.
Use this:
import urllib.request
def readWordList():
response = urllib.request.urlopen("http://www.mit.edu/~ecprice/wordlist.10000")
html = response.read()
data = html.decode('utf-8').split()
return data
to_clean = readWordList() # Use a different name so it won't be replaced later by the function
def clean(aList):
newList = []
for word in aList:
if range(len(word)) >= 2:
newList.append(word)
return newList
clean(to_clean)
Problem solves; now they have different names.

Python Pass function parameter as list identifier

I've created a function which can take a parameter which defines another call to manipulate a list. For example if I call sliprotor(Rotorid1, 1) directly, then the Rotorid1 list is manipulated as I want. Function below:
def sliprotor(rotorid,offset_qty):
for movers in range(26,0,-1):
rotorid[movers-1+offset_qty]=rotorid[movers-1]
for movers_refill in range(offset_qty):
rotorid[movers_refill]=rotorid[movers_refill+26]
However, if I try to call this 'indirectly' by building the list name and then executing it, 'rotorid' is not translated to the value, as it is when called directly.
The way I am doing this is
def set_curr_rotor(XX):
rotorid = "Rotorid"+str(XX)
return rotorid
rid1 = input("First rotor slip : ")
if(rid1):
sliprotor(set_curr_rotor(rid1),1)
So the 'indirect' call doesn't pass the value created by the set_curr_rotor function into the sliprotor function. The direct call does use the passed in value.
If I look in debug, you can see that it is directly calling rotorid[] as the list, not Rotorid1 or other Rotoridx and hence I get an index error.
....
File "", line 3, in sliprotor
rotorid[movers-1+offset_qty]=rotorid[movers-1]
IndexError: string index out of range
I could restructure the way I have the code, but I would prefer not to. Is there some method / scope issue I am missing? Is this just an intrinsic attribute of Python? I'm very new to Python so I'm just doing an exercise to model an Enigma machine.
Any help appreciated.
Ed
I'll assume that you have defined your rotors already, something like this:
Rotorid1 = list('abcdefghijklmnopqrstuvwxyz')
Rotorid2 = list('abcdefghijklmnopqrstuvwxyz')
And now you're reluctant to change this, because ... reasons.
That's fine. But you're still wrong. What you need to do is to create a larger data structure. You can do it like this:
Rotors = [ Rotorid1, Rotorid2, ... ]
Now you have a list-of-lists. The Rotors variable now contains all the various Rotorid variables. (Well, it references them. But that'll do.)
Instead of passing in the variable name as a handle to the rotor, you can simply pass in an index number:
def set_rotor(id):
global Current_rotor
Current_rotor = id
def slip_rotor(amount):
global Current_rotor
global Rotors
rotor = Rotors[Current_rotor]
for movers in range(26,0,-1):
rotor[movers-1+offset_qty]=rotor[movers-1]
# etc...
Also, be sure an look up slicings in Python - you can do a lot by manipulating sublists and substrings using slices.

python inspect.getargspect

Imports a module and then goes through the module's namespace to find any functions (you may assume any object with a call() method is a function) and print the names of the functions and their arguments, in the same way as it might appear in a def statement.
My problem is after I have loop through the module and gotten all the function I can not pass the function name to inspect.getfullargspec() because it is a string.How do i make the string callable?
import inspect
from smtplib import SMTP
from pprint import pprint
def func(x):
for item in inspect.getmembers(x):
lst = inspect.getmembers(x, inspect.isfunction)
for items in lst:
func_names = items[0] #names of functions
f = r"%s.%s" % (x.__name__, func_names)
arg = inspect.getargspec(f)
print(f)
if __name__ == '__main__':
func(SMTP)
You've got a few mistakes in this. The quick answer, though, is that that you don't want to make string callable, you just need to know that inspect.getmembers returns a list of ('func_name', <function object>) pairs, and inspect.getargspec expects a function object.
So you could make your for-loop look like this:
for name, fun in lst:
long_name = r"%s.%s" % (x.__name__, name)
argspec = inspect.getargspec(fun)
print(long_name)
As a separate issue, you rvariable names are mostly nondescriptive and occasionally incorrect. For example, what you call func_names is always exactly one name, and the variable lst would be more usefully named members, and item should be member. Naming a function func is not normally good practice, especially when that function needs several variables inside of that should also, more appropriately, be named func.
lst here is a tuple of function name and function object, you do not really need to do all the string manipulation. Below simple method will do the job:
def func(module):
for lst in inspect.getmembers(module, inspect.isfunction):
if inspect.isfunction(lst[1]):# Doing an additional check, may not be actually required
print(lst[0]+inspect.formatargspec(*inspect.getfullargspec(lst[1])))

Categories

Resources