Using Visual Studio & http://pythontutor.com/visualize I am unable to get the result for filesize function because of the following Error: TypeError: file_size() takes 1 positional argument but 3 were given. Code below.
#this function stores information about a file, its name, its type and its size in bytes.
def file_size(file_info):
name, file_type, size = file_info
return("{:.2f}".format(size/1024))
print(file_size('Class Assignment','docx', 17875)) #Should print 17.46
print(file_size('Notes','txt', 496)) #Should print 0.48
print(file_size('Program','py', 1239)) #Should print 1.21
I though unpacking (file_info) within the function will override the 1 positional argument but 3 were given error. What am I doing wrong?
Currently you are passing three distinct arguments ... pass it instead as one argument which is a tuple:
print(file_size( ('Class Assignment','docx', 17875) ))
Alternatively, you could alter your function declaration to capture distinct arguments into a tuple when called:
def file_size(*file_info):
...
Then calling it as you are is valid.
Put the values into a tuple like this:
print(file_size(('Class Assignment','docx', 17875)))
print(file_size(('Notes','txt', 496)))
print(file_size(('Program','py', 1239)))
This way you are passing one variable
Please try this:
def file_size(file_info):
name, type, size= file_info
return("{:.2f}".format(size / 1024))
Please try this.
def file_size(file_info):
(name,file_type,size) = file_info
return("{:.2f}".format( size/ 1024))
You need to pass file_info in a tuple in python.
If you want to keep the function with one parameter, try assigning the tuple to a variable and pass it in:
file_size(*varname)
Related
I am new to Python and I am struggling with the task of passing a dictionary, whose keys are tuples, as an argument to a function.
mydict = {('hostabc', 'pola'): 333444567, ('hostdef', 'polb'): 111222333, ('hostghi', 'polc'): 222999888}
def tupletest(**kwargs):
print(kwargs)
tupletest(**mydict)
The following keyword error is generated:
TypeError Traceback (most recent call last)
<ipython-input-29-fec409a1eb53> in <module>
2 def tupletest(**kwargs):
3 print(kwargs)
----> 4 tupletest(**mydict)
TypeError: tupletest() keywords must be strings
I am unsure if this is even possible given the error msg. I am testing this in 3.7.4
All help appreciated.
I performed a little example. It ist possible:
mydict = {('hostabc', 'pola'): 333444567, ('hostdef', 'polb'): 111222333, ('hostghi', 'polc'): 222999888}
def tupletest(kwargs):
for key in kwargs:
#print("key: %s , value: %s" % (key, kwargs[key]))
print(key[0])
print(key[1])
tupletest(mydict)
I hope this helps you. I also implemented a little example for entering the key of the dictionary.
Output
Short answer is, no it's not possible.
complex(real=3, imag=5)
complex(**{'real': 3, 'imag': 5})
**kwargs represents keyword arguments. These arguments are unpacked (so to say) and passed to the function. That way you can use them in the function without having to explicitly pass them to the function as the positional-or-keyword arguments.
def func(*args, **kwargs): ...
var-keyword: specifies that arbitrarily many keyword arguments can be
provided (in addition to any keyword arguments already accepted by
other parameters). Such a parameter can be defined by prepending the
parameter name with **, for example kwargs in the example above.
https://docs.python.org/3/glossary.html#term-argument
#BoarGules has nicely pointed you to the path. I have nothing new to add and I am saying below the same thing but in a little verbose manner.
See this nice discussion here. So dictionary keys become the named parameters to the function. In this particular case however the keys are tuples. The keyword must have an associated string property and that is what the error is saying above. Notice the "strings" in the error message below.
TypeError: tupletest() keywords must be strings
Had your dictionary been simpler like below, it would have worked.
mydict = {"a": 333444567, "b": 111222333, "c": 222999888}
def tupletest(**kwargs):
for k in kwargs:
print(k)
tupletest(**mydict)
The above gives this.
a
b
c
If you would rather want to have the tuples, I will take the dangerous route of eval after quoting the tuples.
mydict = {"('hostabc', 'pola')": 333444567, "('hostdef', 'polb')": 111222333, "('hostghi', 'polc')": 222999888}
def tupletest(**kwargs):
for k in kwargs:
print(eval(k))
tupletest(**mydict)
This gives the following output.
('hostabc', 'pola')
('hostdef', 'polb')
('hostghi', 'polc')
I am quite new to python and probably facing a very simple problem. However, I was not able to find a solution via Google, as the information I found indicated my method should work.
All I want to do is passing in an array as argument to a function.
The function that shall take an array:
def load(components):
global status
global numberOfLoadedPremixables
results = []
print('componetnsJson: ', componentsJson, file=sys.stderr)
status = statusConstants.LOADING
for x in range(0, len(components)):
blink(3)
gramm = components[x]['Gramm']
#outcome = load(gramm)
time.sleep(10)
outcome = 3
results.append(outcome)
numberOfLoadedPremixables += 1
status = statusConstants.LOADING_FINISHED
Then I am trying to start this function on a background thread:
background_thread = threading.Thread(target=load, args=[1,2,3]) #[1,2,3] only for testing
background_thread.start()
As a result, I end up with the error:
TypeError: load() takes 1 positional argument but 3 were given
Since you need to pass the whole array as a single unit to the function, wrap that in a tuple:
background_thread = threading.Thread(target=load, args=([1,2,3],))
The (,) turns the args into a single-element tuple that gets passed to your function
The issue is happening because python expects args to be a sequence which gets unwrapped when being passed to the function, so your function was actually being called like: load(1, 2, 3)
I have a function def findSpace(aBookcase): which returns return row,column and another function which takes def setName(self, row, column, name):.
Now, when I execute aBookcase.setName(findSpace(aBookcase), name) I get TypeError: setName() takes exactly 4 arguments (3 given).
How can I make it parse the result from findSpace() as two arguments to function setName(), without changing findSpace(), because I have other code already depend on it
findSpace returns a tuple. That is one object. aBookcase.setName expects three separate arguments, in addition to the instance itself. Unpack the result and then use the arguments:
r,c = findSpace(aBookcase)
aBookcase.setName(r, c, name)
In Python 3.5 or higher, you can simply use *:
aBookcase.setName(*findSpace(aBookcase), name)
The issue here is I want to pass a tuple as an argument to a second function. Before there are outcries of "duplicate!" I have already looked at a post regarding a similar question Expanding tuples into arguments
Here is the code I am testing with:
def producer():
return ('a','b')
def consumer(first, second, third):
print first+second+third
arg = producer()
consumer(*arg, 'c') # expected abc
This outputs the error:
There's an error in your program *** only named arguments may follow *expression
This useful error message has led switch the order of arguments to consumer('c', *arg), but this does not quite solve the issue as it will output 'cab'.
So my question is, is there a better way to pass in a tuple to a multi argument function, and preserve the ordering?
Also for bonus points, what does the '*' operator do? (this was not explained in the previous post)
As the error message states, Python does not allow you to have unnamed arguments after *arg.
Therefore, you need to explicitly name third:
>>> def producer():
... return ('a','b')
...
>>> def consumer(first, second, third):
... print first+second+third
...
>>> arg = producer()
>>> consumer(*arg, third='c')
abc
>>>
If you need to add an argument, concatenate the tuple:
arg += ('c',)
consumer(*arg)
Alternatively, you can name the argument explicitly by using a keyword parameter:
consumer(third='c', *arg)
You cannot put more positional arguments after *arg, these are always added to any explicit positional arguments.
I've been looking at passing arrays, or lists, as Python tends to call them, into a function.
I read something about using *args, such as:
def someFunc(*args)
for x in args
print x
But not sure if this is right/wrong. Nothing seems to work as I want. I'm used to be able to pass arrays into PHP function with ease and this is confusing me. It also seems I can't do this:
def someFunc(*args, someString)
As it throws up an error.
I think I've just got myself completely confused and looking for someone to clear it up for me.
When you define your function using this syntax:
def someFunc(*args):
for x in args
print x
You're telling it that you expect a variable number of arguments. If you want to pass in a List (Array from other languages) you'd do something like this:
def someFunc(myList = [], *args):
for x in myList:
print x
Then you can call it with this:
items = [1,2,3,4,5]
someFunc(items)
You need to define named arguments before variable arguments, and variable arguments before keyword arguments. You can also have this:
def someFunc(arg1, arg2, arg3, *args, **kwargs):
for x in args
print x
Which requires at least three arguments, and supports variable numbers of other arguments and keyword arguments.
You can pass lists just like other types:
l = [1,2,3]
def stuff(a):
for x in a:
print a
stuff(l)
This prints the list l. Keep in mind lists are passed as references not as a deep copy.
You don't need to use the asterisk to accept a list.
Simply give the argument a name in the definition, and pass in a list like
def takes_list(a_list):
for item in a_list:
print item
Python lists (which are not just arrays because their size can be changed on the fly) are normal Python objects and can be passed in to functions as any variable. The * syntax is used for unpacking lists, which is probably not something you want to do now.
def sumlist(items=[]):
sum = 0
for i in items:
sum += i
return sum
t=sumlist([2,4,8,1])
print(t)