Pycharm delete all unexpected argument - python

I got a method or __init__ with multiple argument, then I realize I do not need that argument so I delete it and rewrite the method. Now I have a lot of method/init call which have more argument than the method itself, resulting to unexpected argument.
I have a lot more unexpected argument than what the image shows, so much that I hope I do not need to delete the argument manually by hand. Is there any way to delete all unexpected argument automatically in PyCharm?
I do not want to silent the warning, I want to delete all the unexpected argument.
Simplified and exaggerated example of my problem
def foo(number):
pass
# code here ....
foo(1, "function call number 1")
foo(2, "function call number 2")
foo(3, "function call number 3")
.......
foo(1156, "function call number 1156")

Related

Why does function run without paramater?

I'm currently learning curses in python, and I found this piece of code online that is confusing me.
import curses
def draw_menu(stdscr):
# do stuff
# if you want more code just let me know
def main():
curses.wrapper(draw_menu)
if __name__ == "__main__":
main()
When I run this I don't get the expected missing 1 required positional argument error, since there is no parameter being passed in the curses.wrapper(draw_menu) line. Is this a curses thing? Any help is greatly appreciated.
A function is a datatype, just as much as strings, integers, and so on.
def my_function(txt):
print(txt)
here type(my_function) # => <class 'function'>
You invoke the code inside the function when you call it with parenthesis : my_function('hello') # => prints hello
Until then you can perfectly pass a function as an argument to another function.
And that last one can call the one you passed giving it some parameters.
Like in your case, I'd guess that curses.wrapper() creates a screen interface that it passes as argument your draw_menu() function.
And you can probably use that screen object to build your curse app.
See this : Python function as a function argument?
There's a big difference between curses.wrapper(draw_menu) and curses.wrapper(draw_menu()). curses.wrapper(draw_menu) calls curses.wrapper and passes the function draw_menu into it as an argument. In contrast, curses.wrapper(draw_menu()) would call draw_menu and pass its return value into curses.wrapper.
curses.wrapper will call the function you pass it. From that link:
Initialize curses and call another callable object, func, which should be the rest of your curses-using application.
E.g., it will call draw_menu when curses is completely initialized.
Here is the signature for curses.wrapper from here.
curses.wrapper(func, /, *args, **kwargs)
It says that you need to give curses.wrapper a function reference argument followed by zero or more arguments and keyword arguments. Your code satisfies those requirements.
Python allows function signatures like this to enable developers a lot of flexibility regarding what can be passed in by the caller.

class employee print method

I am studying classes in python programming in jupyter notebooks and google colab.
I don't understand the results with respect to this class.
class employee_constructor():
def __init__(self,name,surname,salary):
self.name=name
self.surname=surname
self.salary=salary
def increasesalary(self,percentage):
self.salary=self.salary*(1+percentage/100)
def displayEmployee(self):
print('this employee is {} and gets {} dollars'.format(emp1.name,emp1.salary))
now I try to print out results:
emp1=employee_constructor('jose','ferro',1000)
emp2=employee_constructor('manolo','rod','1500')
emp1.displayEmployee
print('before increase',emp1.salary)
emp1.increasesalary(5)
emp1.increasesalary(5)
print('after increase',emp1.salary)
print(emp1.salary)
# this line does not give error and does nothing:
emp1.increasesalary
print(emp1.salary)
# this line gives error:
# increasesalary() missing 1 required positional argument: 'percentage'
emp1.increasesalary()
I don't understand why running the method without the parenthesis would not cause any error (actually the method is not run) whereas with the parenthesis (and not passing the neccesary variable through an error)
secondly, how can I avoid such kind of errors? i.e. if the user passes nothing assume vale zero
note:
this question explains init method and was proposed as solution. My question is related but is not answered there
I don't understand why running the method without the parenthesis would not cause any error (actually the method is not run) whereas with the parenthesis (and not passing the neccesary variable through an error)
When you refer a method (function in the context of an object, self is passed implicitly) by object.method the method object is returned. But to actually execute the function you need to call it i.e. use the parentheses.
For fun, save the returned method object as a variable and call that instead, you'll see that you're doing the same thing as they refer to the same object.
Now, when you called emp1.increasesalary(), you didn't pass the required argument percentage leading to the error. Note again, the self (object itself) is passed implicitly.
how can I avoid such kind of errors? i.e. if the user passes nothing assume vale zero
Make the argument a keyword argument with a default value of 0:
def increasesalary(self, percentage=0):
self.salary = self.salary * (1 + percentage / 100)
you can always use a funtion (without parenthesis) in python:
def f():
pass
print(f)
this will not call the function but just print out its memory location. so a line containing the function f itself is a valid python statement; but it does not call the function.
then: you need to use self and not emp1 in your displayEmployee(self) method:
def displayEmployee(self):
print('this employee is {} and gets {} dollars'.format(self.name, self.salary))
better:
def __str__(self):
return f"this employee is {self.name} and gets {self.salary} dollars"
then you can
print(emp1)

regarding the correct way to call a function

Suppose there is a function defined as
def function1(x, y, z=True,a):
...
...
When I call function1, it seems I can call the function in the following manners
function1(10,2,3)
function1(x=10,y=2,a=3)
But calling function1(x=10,y=2, 3) will cause error, where 3 should be assigned to a. Generally, what are the correct ways to call a function withou causing potential issues.
That is not a valid way to define a function in python 2 or 3. Default arguments (ones with default values, namely x=y) must come after non-default arguments. With your function definition, you should receive the following error:
File "<stdin>", line 1
SyntaxError: non-default argument follows default argument

It says "TypeError: Oppnadjur() takes exactly 1 argument (0 given)" why?

so this is my function, and it doesn't work.. why?
def Oppnadjur(djurfil):
djurfil = open("djur.txt", "r")
Djur = djurfil.readlines()
Djur.sort()
djurfil.close()
Djurlista=[]
You wrote that your function should receive one parameter, djurfil. However, you clearly did not mean to do that, as you proceed to not use that parameter, overwriting it with a different value. See the Python Tutorial about how to define functions.
The error message you see means that you had called your function as you had intended, with no parameters (Opnnadjur()), but that's not how you had defined it. So Python is looking for the parameter it thinks you should be passing in.
The error would be in your calling code, not the def of the function. You need to call Oppnadjur with one parameter. The error message suggests that you are calling it with zero parameters.
You define your function with one argument (djurfil), but the argument is unused in your function so you can get rid of it.
def Oppnadjur():
djurfil = open("djur.txt", "r")
Djur = djurfil.readlines()
Djur.sort()
djurfil.close()
Djurlista=[]

Python mandatoryl arbitrary argument list *args

is there any way to define a mandatory *args (arbitrary arguments) in a method of a class?
class foo():
def __init__(self,*args):
....
Given this, you can create an object from the foo-class without any arguments x=foo(), i.e. its optional. Any ideas how to change it to a non-optional or "give me at least one arguments"-thing?
Another questions concerns the list unpacking with x=foo(*list) --> Is there a way to recognize the list as a list and unpack the list automatically, so that you donĀ“t have to use the * in a function/method call?
Thx
*args is meant to receive all arguments that are not already taken by normal arguments.
Usually if you need an argument to be mandatory, you just use a normal argument:
>>> def foo(arg, *rest):
... print arg, rest
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes at least 1 argument (0 given)
If you think it is more elegant to gather all arguments in a tuple, you have to handle the error case yourself:
>>> def foo(*args):
... if len(args) < 1:
... raise TypeError('foo() takes at least 1 argument (%i given)' % len(args))
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in foo
TypeError: foo() takes at least 1 argument (0 given)
But as you can (or should) see, from the signature of that function it is not clear how many arguments to that function are mandatory to anyone who uses that function. You should either avoid this altogether or at least document it very well.
There are other problems as well: if you give on argument to foo() that is iterable (like a string), you will not get the intended result.
Responding to your comment below, your first approach was the right one: take a list.
def scrape(urls):
for url in urls:
do_something(url)
The caller simply has to pass a list with only one element: scrape(['localhost']).
Even better would probably be to take only one URL and let the caller iterate over a list. In that case the caller could parallelize the operations if she ever wants to.
As to your second question1: either you function takes a list as an argument or it doesn't. Either it makes sense in your program to pass around lists or it doesn't.
I guess, I'm not entirely sure what you are asking there, but then again your whole question sounds like you found a shiny new tool and now you want to use it everywhere, regardless of whether it makes sense or not.
1 please don't ask more than one question at once!
Either test the length of the resultant tuple, or put one or more normal arguments before it.
No.
For "give me at least one argument," just check the len() of the tuple you receive and throw an exception if you don't get at least one. Here I am using the fact that empty tuples are "falsy" to do that implicitly:
def __init__(self, *args):
if not args:
raise TypeError("__init__ takes at least 2 arguments (1 given)")
For "auto-unpacking," you will also need to test for this and perform it yourself. One method might be:
if len(args) == 1 and not isinstance(args[0], basestring) and iter(args[0]):
args = args[0]
The iter() will always be true, but if what you pass it is not iterable, it will raise an exception. If you want to provide a friendlier error message, you could catch it and raise something else.
Another alternative would be to write your method so that it recursively iterates over all elemets of args and all subcontainers within it; then it doesn't matter.
Or, you know, just have the caller pass in an iterable to begin with, and don't mess with *args. If the caller wants to pass in a single item, there is simple syntax to turn it into a list: foo([item])

Categories

Resources