I defined a function which takes 2 arguments. When I call the function, I get an error saying not enough argument:
>>> def fib(self, a,b):
... self.i=a, self.j=b
... print self.i+self.j
...
>>> fib(4,8)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fib() takes exactly 3 arguments (2 given)
>>> fib(4,8,9)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in fib
AttributeError: 'int' object has no attribute 'i'
I passed with both 2 and 3 arguments. What should be the third argument?
I am assuming you don't understand self very well in python. Its heading towards OOP (Object oriented programming).
non-OOP approach (doing the same thing with static methods)
def fib(a,b):
print a+b
fib(4,8)
OOP approach
class Test():
i = 0
j = 0
def fib(self, a,b):
self.i=a
self.j=b
print self.i+self.j
t = Test() # create an object of Test class
t.fib(2, 3) # make the function call
NOTE : python considers a function to be a static function if it does not have the keyword self as the first parameter
You function has 3 arguments: self, a and b.
self is traditionally used for methods.
You write (simplified example):
class A:
def multiply(self, b): # method called with one argument
return 2 * b
a = A()
a.multiply(3)
or
def multiply(b): # this is a function with one argument
return 2*b
mutiply(3)
Related
Here's a simple function with a local function:
def raise_to(exp):
def raise_to_exp(x, exp):
return pow(x, exp)
return raise_to_exp
Now I expect the local function to close over exp, but somehow it doesn't. When I run this:
square = raise_to(2)
print(square.__closure__)
I get None. What am I missing?
There is no closure, no, because the inner function has it's own local exp variable; you gave it a parameter by that name. The parameter masks the name in the outer scope, so no closure is created for it. The function that is returned requires two arguments, and the argument to raise_to() is simply ignored:
>>> from inspect import signature
>>> def raise_to(exp):
... def raise_to_exp(x, exp):
... return pow(x, exp)
... return raise_to_exp
...
>>> signature(raise_to(2))
<Signature (x, exp)>
>>> square = raise_to(2)
>>> square(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: raise_to_exp() missing 1 required positional argument: 'exp'
>>> square(5, 3)
125
>>> raise_to('This is ignored, really')(5, 3)
125
Remove the exp parameter from the inner function if you wanted that to be taken from the outer function:
def raise_to(exp):
def raise_to_exp(x):
return pow(x, exp)
return raise_to_exp
Now exp is a closure:
>>> def raise_to(exp):
... def raise_to_exp(x):
... return pow(x, exp)
... return raise_to_exp
...
>>> raise_to(2).__closure__
(<cell at 0x11041a978: int object at 0x10d908ae0>,)
>>> raise_to.__code__.co_cellvars
('exp',)
The co_cellvars attribute on a code object gives you the names of any closed-over variable in the outer scope.
The function that is returned takes one argument, and the argument to raise_to() is now actually used:
>>> raise_to(2)(5)
25
>>> raise_to('Incorrect type for pow()')(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in raise_to_exp
TypeError: unsupported operand type(s) for ** or pow(): 'int' and 'str'
I am used to having function/method definitions like so in Python:
def my_function(arg1=None , arg2='default'):
... do stuff here
If I don't supply arg1 (or arg2), then the default value of None (or 'default') is assigned.
Can I specify keyword arguments like this, but without a default value? I would expect it to raise an error if the argument was not supplied.
You can in modern Python (3, that is):
>>> def func(*, name1, name2):
... print(name1, name2)
...
>>> func()
Traceback (most recent call last):
File "<ipython-input-5-08a2da4138f6>", line 1, in <module>
func()
TypeError: func() missing 2 required keyword-only arguments: 'name1' and 'name2'
>>> func("Fred", "Bob")
Traceback (most recent call last):
File "<ipython-input-7-14386ea74437>", line 1, in <module>
func("Fred", "Bob")
TypeError: func() takes 0 positional arguments but 2 were given
>>> func(name1="Fred", name2="Bob")
Fred Bob
Any argument can be given as with a keyword expression, whether or not it has a default:
def foo(a, b):
return a - b
foo(2, 1) # Returns 1
foo(a=2, b=1) # Returns 1
foo(b=2, a=1) # Returns -1
foo() # Raises an error
If you want to force the arguments to be keyword-only, then see DSM's answer, but that didn't seem like what you were really asking.
class DLLNode(object):
def __init__(self, data, prev_link, next_link):
self.data = data
self.prev_link = prev_link
self.next_link = next_link
class DoublyLinkedList(object):
def __init__(self):
self.head=None
self.tail=None
def add_head(self, add_obj):
self.head=DLLNode(add_obj,None,self.head)
>>> x=DoublyLinkedList
>>> x.add_head(1)
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
x.add_head(1)
TypeError: add_head() takes exactly 2 arguments (1 given)
Guessing x isn't counting as an argument because it's not getting instantiated right.
x = DoublyLinkedList()
not
x = DoublyLinkedList
not including parens assigns the DoublyLinkedList module object to x, it doesn't create a new one.
When you write
x = DoublyLinkedList
you assign the class DoublyLinkedList to x, not an instance of it. add_head being an instance method, it cannot be called on the class directly. Instead, you need to use
x = DoublyLinkedList()
x.add_head(1)
This way, python will be able to substitute self with x, and you will have 2 arguments to your call.
You need to create an instance of the object when assigning to x
x = DoublyLinkedList()
The former syntax (DoubleLinkedList) is allowed because classes are valid as objects.
from celery.task import Task
class Decayer(Task):
def calc_decay_value(self, x):
y = (1.0/(2^x))
return y
def calc_decay_time(self, x):
y = 2^x
return y
def run(self, d, **kwargs):
#do stuff.
return 0
>>> decayer = tasks.Decayer(r)
Traceback (most recent call last):
File "scanDecay.py", line 31, in <module>
decayer = tasks.Decayer(r)
TypeError: object.__new__() takes no parameters
Two errors
1) Your class doesn't have an __init__ function. Either add one, or use this instead:
decayer = tasks.Decayer()
2) You are trying to raise an integer to the power of a float, but ^ means xor and cannot be used on floats. Use ** instead of ^:
y = 2 ** x
The problem seems due to decayer = tasks.Decayer(r) call and tasks.Decayer is not designed to take a argument, because Task does not define a __init__ method which can take one.
is to possible to "pack" arguments in python? I have the following functions in the library, that I can't change (simplified):
def g(a,b=2):
print a,b
def f(arg):
g(arg)
I can do
o={'a':10,'b':20}
g(**o)
10 20
but can I/how do I pass this through f?
That's what I don't want:
f(**o)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() got an unexpected keyword argument 'a'
f(o)
{'a': 10, 'b': 20} 2
f has to accept arbitrary (positional and) keyword arguments:
def f(*args, **kwargs):
g(*args, **kwargs)
If you don't want f to accept positional arguments, leave out the *args part.