How can I pass dictionary to a function in python? - python

I am trying to pass dictionary to a function in python but it shows me error.
class stud:
def method(**arg):
print(arg)
dict1 = {1:"abc",2:"xyz"}
a = stud()
a.method(dict1)
This raises the following error:
>>> a.method(dict1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: method() takes 0 positional arguments but 2 were given
Can you tell me were I goes wrong or the right way to pass dictionary to a function?

As #Bit mentions, if method is not a static method. You need to add a self parameter.
There are two options here:
you use a normal parameter in the method:
class stud:
def method(self,arg): # normal parameter
print(arg)
you pass the dictionary as named parameters in the call:
class stud:
def method(self,**arg): # normal parameter
print(arg)
a.method(**dict1)
Personally I would go with the first one, since it is:
more efficient: you pass only a reference to the dictionary; and
if you want to alter the original dictionary, that is still possible.

Related

How can I invoke Python's built-in function argument verification without calling the function?

Python obviously has a way to verify whether a function call has valid arguments (correct number of positional arguments, correct keyword arguments, etc). The following is a basic example of what I mean:
def test_func(x, y, z=None):
print(x, y, z)
test_func(2) # Raises a "missing positional argument" TypeError
test_func(1, 2, 3, a=5) # Raises an "unexpected keyword argument" TypeError
Is there a way that I can use this argument verification, without actually calling the function?
I'm basically trying to write a decorator that does some preprocessing steps based on the function arguments before calling the wrapped function itself, such as:
def preprocess(func):
def wrapper(*args, **kwargs):
# Verify *args and **kwargs are valid for the original function.
# I want the exact behavior of calling func() in the case of bad arguments,
# but without actually calling func() if the arguments are ok.
preprocess_stuff(*args, **kwargs)
func(*args, **kwargs)
return wrapper
I want my wrapper function to verify that the arguments would be valid if used on the wrapped function before doing any preprocessing work.
I would like to take advantage of the checks Python already does every time you call a function and the various exceptions it will raise. I just do not want to actually call the function, because the function may not be idempotent. Writing my own checks and exceptions feels like reinventing the wheel.
You can't invoke the actual built-in argument verification for a function without calling the function, but you can use something pretty close.
The inspect module has a function signature(), which returns a Signature object representing the argument signature of the function passed to it. That Signature object has a bind() method which attempts to create a BoundArguments object using the arguments passed to it. If those arguments don't match the signature, a TypeError is raised.
While this mostly behaves like the built-in argument binding logic, it has a few differences. For example, it can't always determine the signature of functions written in C, and its interaction with decorators will depend on whether they use functools.wraps (or something else that sets the __wrapped__ attribute). That said, since the real argument binding logic is inaccessible, inspect.signature is the best alternative.
We can use all this to create your decorator:
import functools
import inspect
def preprocess(func):
sig = inspect.signature(func)
#functools.wraps(func)
def wrapper(*args, **kwargs):
try:
sig.bind(*args, **kwargs)
except TypeError:
pass # bad arguments; skip preprocessing
else:
print("Preprocessing: args=%r, kwargs=%r" % (args, kwargs))
# ... etc.
return func(*args, **kwargs)
return wrapper
Usage:
#preprocess
def test_func(x, y, z=None):
print(x, y, z)
>>> test_func(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in wrapper
TypeError: test_func() missing 1 required positional argument: 'y'
>>> test_func(1, 2, 3, a=5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in wrapper
TypeError: test_func() got an unexpected keyword argument 'a'
>>> test_func(1, 2)
Preprocessing: args=(1, 2), kwargs={}
1 2 None
Note that, if bad arguments are supplied, you do in fact want to call the function, because you "want the exact behavior of calling func() in the case of bad arguments" (to quote your comment), and the only way of getting the exact behaviour of calling an arbitrary function (even if that behaviour is to immediately fail) is to actually call it. What you don't want to do in such cases is the preprocessing, which the decorator above achieves for you.

kwargs to python instance method

I need to pass a kwargs to a Python instance method but get the following error below.
class test(object):
def __init__(self):
print 'Initializaed'
def testmethod(self,**kwargs):
for each in kwargs:
print each
x = test()
x.testmethod({"name":"mike","age":200})
Error:
Traceback (most recent call last):
File "C:\Users\AN\workspace\Scratch\Scratch\test.py", line 20, in <module>
x.testmethod({"name":"mike","age":200})
TypeError: testmethod() takes exactly 1 argument (2 given)
x.testmethod({"name":"mike","age":200})
This invokes testmethod() with two positional arguments - one is implicit (the object instance, i.e. self) and the other one is the dictionary you gave it.
To pass in keyword arguments, use the ** operator for unpacking your dictionary into key=value pairs, like this:
x.testmethod(**{"name":"mike","age":200})
This translates to x.testmethod(name='mike', age=200) which is what you want. You can also read about argument unpacking in the documentation.

calling dynamically to class method based on command line arguments

I need to call the class methods based on the command line argument
params = sys.argv[1].split('.')
print params
['Abc', 'test']
suite.addTest(params[0](params[1]))
Traceback (most recent call last):
File "policy.py", line 407, in <module>
suite.addTest(params[0](params[1]))
TypeError: 'str' object is not callable
Is their any way to call a class method.
In your code, params[0] is still the string 'Abc'. You need to transform it into a class that you can call.
Suppose class Abc is in module foo. Then you can do this--
import foo
MyTestClass = getattr(foo, params[0])
suite.addTest(MyTestClass(params[1])
The quick way to do it is using eval which will take the string and evaluate it in the current namespace. But eval is evil since your program input could look something like:
eval("os.remove('/')")
just as an example. Python also has a dictionary of the globals you can use this:
TestClass = globals()[params[0]]
suite.addTest(TestClass(params[1])

Strange extra argument

I got the following python code where printSaved is called when a button is clicked (using the wx library and python 2.7.2). But when this happens i got a really strange error
Traceback (most recent call last):
File "./program.py", line 135, in printSaved
s = self.readSaved()
TypeError: readSaved() takes no arguments (1 given)
Here is the code
def readSaved():
f = codecs.open((os.getenv('HOME') +'/Dokument/savefile.txt') ,'r','utf-8')
l = f.readlines()
f.close()
return l
def printSaved(self,event):
s = self.readSaved()
for l in s:
print l
I fixed the problem by adding one argument to readSaved(somethingUseless) and everything worked fine. My question is what is passed to readSaved and HOW/WHY? Does this have something to do with the event?
In Python, the object on which a method is called is always passed in explicitly as an argument. This argument is conventionally called self.
The correct definition for readSaved() as an instance method should have this as the first line:
def readSaved(self):
# ...
If you want it to be a module-level function, you should call it as follows:
s = readSaved()
Methods are passed the instance as the first argument.
Is it defined within a class? I suppose it does, since the second method takes self.
If readSaved is an instance method, it takes self as first parameter as well. If you don't need it, use the #staticmethod decorator instead:
#staticmethod
def readSaved():
f = codecs.open((os.getenv('HOME') +'/Dokument/savefile.txt') ,'r','utf-8')
l = f.readlines()
f.close()
return l
As it is a method -- you're calling it as a method, anyway -- you have to have at least self as an argument. When a function is called as a method, the object you call the method through is passed as the first argument to that function.

Python 3.1.1 Class Question

I'm a new Python programmer who is having a little trouble using 'self' in classes. For example:
class data:
def __init__(self):
self.table = []
def add(self, file):
self.table.append(file)
data.add('yes')
In this function I want to have table be a variable stored in the class data and use add to modify it. However, when I run this script it gives me the error:
Traceback (most recent call last):
File "/Projects/Python/sfdfs.py", line 7, in <module>
data.add('yes')
TypeError: add() takes exactly 2 positional arguments (1 given)
I assume that I am trying to call the function the wrong way in this instance, as this syntax is very similar to an example in the python documentation: http://docs.python.org/3.1/tutorial/classes.html
You first need to make an instance of the class:
mydata = data()
then you can call the method -- on the instance, of course, not on the class:
mydata.add('yes')
You need to instantiate the class before you can call methods on it:
mydata = Data()
mydata.add('yes')
you are calling the add method on the class object not an instance of the class.
It looks like what you want to do is:
classInst = data() #make an instance
classInst.add("stuff") #call the method
When add is invoked on an instance object, the instance object is passed as the self argument to the method. Having the self argument differentiates class methods from instance methods.
You are trying to call data.add() somewhat like you would call a static method in Java.
Try doing this instead:
d = data()
d.add('yes')
The self parameter tells the method that it operates on an object of type data.

Categories