I am trying to construct a dispatch the following way:
def run_nn(type=None):
print type, 'nn'
return
def run_svm(type=None):
print type, 'svm'
return
action = {'nn' : run_nn( type=None),
'svm' : run_svm(type=None),}
I want the function to be executed only when called with something like:
action.get('nn',type='foo')
With expectation it to print:
foo nn
But it breaks giving:
TypeError: get() takes no keyword arguments
What's the right way to do it?
Furthermore, two functions run_nn() and run_svm() were executed without even being called. I don't want that. How can I avoid it?
You're calling the functions while building the dictionary. You should instead put the function objects in the dict without calling them. And afterwards, get the appropriate function from the dict and call it with the keyword argument.
What you want is:
action = {'nn' : run_nn,
'svm' : run_svm,}
...
action.get('nn')(type='foo') # get function object from dict and then call it.
I'll suggest you use action['nn'] over action.get('nn') since you're not specifying any default callable in the get method; the get method returns None when you don't specify one. A KeyError is much more intuitive than a TypeError NoneType object is not callable in this scenario.
On another note, you can drop those return statements as you aren't actually returning anything. Your function will still return without them.
BTW, I have the feeling your function(s) want to change behavior depending on type (although your type is counter-intuitive as it is always a string). In any case, you may have a look at functools.singledispatch. That'll transform your function(s) into a single-dispatch generic function with the possibility to create several overloaded implementations.
Finally, although type does make for a good argument name, you will run into problems when you need to use the builtin type in your function.
Related
I need a script that given a function returns the arguments of a specific decorator.
Imagine the following function:
#decorator_a
#decorator_b(41,42,43)
#decorator_c(45)
def foo(self):
return 'bar'
I need a function that given foo returns the arguments of decorator_b - something like [41,42,43]. Is there a way to achieve this?
After a few hours of trying out different stuff I figured out a feasible solution:
inspect.getclosurevars(foo.__wrapped__).nonlocals
If you know the argument names of the decorator you try to inspect you can check for existence in the nonlocals dict. If it's not there, check one __wrapped__ layer higher and so on.
Please forgive my noob status, but I have come across a construct I don't really understand and hope someone can explain it for me.
class Base(object):
def mogrify(self, column):
return self.mogrifiers.get(column.lower().strip()) or (lambda x: x)
...
class MyClass(some.package.Base):
def mogrifiers(self):
return {
'column1': (lambda x: datetime.datetime.fromtimestamp(int(x)))
}
...
class MyOtherClass(object):
def convert_columns:
...
new_row[colkey] = self.myclass.mogrify(colkey)(value)
This all works, but I'm trying to write a unit test and mock out MyClass.
As far as I can tell, mogrifiers returns a dictionary of all the columns and any transformations that are required.
The code I am testing calls mogrify (inherited from the Base class) with a specific column name in a string.
This tries to extract the column from the dictionary and returns the lambda function ? or if it doesn't exist in the dictionary, it returns a lambda that just gives the string back ?
So that just leaves me with the (value) bit in the code I'm trying to test. It's no clear what it does.
If I don't want to test the underlying conversion/transformation my mock could just return the simple lambda.
So I've done that, but it throws an exception on the call to mogrify saying:
E TypeError: 'str' object is not callable
Can anyone provide some clues what I'm missing here?
As far as I can tell, mogrifiers returns a dictionary of all the
columns and any transformations that are required.
That is correct, though as you've shown it it will create a fresh dictionary each time which seems unnecessary.
The code I am testing calls mogrify (inherited from the Base class)
with a specific column name in a string.
This tries to extract the column from the dictionary and returns the
lambda function ? or if it doesn't exist in the dictionary, it returns
a lambada that just gives the string back ?
Yes, that is also correct (except that a lambada is a dance, but I think you meant lambda again).
So that just leaves me with the (value) bit in the code I'm trying to
test. It's no clear what it does.
The call self.myclass.mogrify(colkey) returns a callable, the (value) simply calls it. It may be clearer if I rewrite like this:
fn = self.myclass.mogrify(colkey)
new_row[colkey] = fn(value)
splitting it into two lines will also make it clearer whether the problem is with the call self.myclass.mogrify(colkey) or fn(value). If as seems likely it is the fn(value) call it means your mocked mogrify is returning a str instead of returning a callable; it could however be that you got the mock wrong and the mocked mogrify method is actually a string.
I would suggest you rewrite as shown and also insert a print between the two lines and see what is actually being returned.
I am trying to pass a dict variable into a function in Python 3 and then trying to iterate through the keys by calling the .keys() function. However I don't know how to specify the type of the parameter.
def DisplayStock(StockDict):
for key in StockDict.keys():
The error I am getting is
for key in StockDict.keys():
AttributeError: 'function' object has no attribute 'keys'
I guess You ask about pep-484
def DisplayStock(StockDict: dict):
for key in StockDict.keys()
StockDict is a parameter name, dict is a parameter type.
It seems like you are just passing something wrong to the function. From the error it seems like you are giving it a function. Maybe you should put () behind the argument that is causing the error.
Normally you don't need to specify a type. The function will take any type.
If you want to check if the passed argument is a dict you could use:
if isinstance(Stockdict, dict):
for key in Stockdict.keys()
This is not very pythonic though. Just don't pass a non dict like object to the function.
The problem is not in the parameter type. Python is happy for just a variable name and as the original code and then use the .keys method. The error was in a different part of the code I missed brackets on a function call and had set my dictionary object to be a function reference.
So, I would like to modify the json.loads() function to accept a new keyword parameter, but not have it just be a part of kwargs. In other words, I want it be an explicit part of the function's signature.
Here's my guess on how to do this. Are there better ways of doing this?
def json_to_python_syntax(json_method):
"""
Translate JSON-conforming key names to Pythonic standards on dict.
The goal of this decorator is to add a standard keyword parameter
'convert_syntax' onto the method. But, I'm not sure how to do this.
"""
#wraps(json_method)
def wrapper(json_string, convert_syntax=False, **kwargs):
pythonic_dict = dict()
json_syntax_dict = json_method(json_string, **kwargs)
if not convert_syntax:
return json_syntax_dict
for key, value in json_syntax_dict.iteritems():
for json_syntax in re.finditer(r'[A-Z]', key):
key = key.replace(
json_syntax.group(), '_' + json_syntax.group()[0].lower())
pythonic_dict[key] = value
return pythonic_dict
return wrapper
My concern with this method is that it this monkeys with the expected order of keyword parameters in json.loads (It makes convert_syntax the first expected parameter after the json string) and could mess up other calls to json.loads within the larger program that assume the standard order.
Seeing as your change breaks the expected signature of json.loads and you're concerned with it breaking other code that depends on the original signature, I'd agree with Simeon Visser, seems like you shouldn't do this at all.
Only code you write will be able to properly call your new method, so why not give your method a different name, rather than decorating an existing method? If you want to prevent other code from calling this method without the convert_syntax flag, just avoid importing the json module at all, and instead import your json library that wraps the json module.
I have several layers of function calls, passing around a common dictionary of key word arguments:
def func1(**qwargs):
func2(**qwargs)
func3(**qwargs)
I would like to supply some default arguments in some of the subsequent function calls, something like this:
def func1(**qwargs):
func2(arg = qwargs.get("arg", default), **qwargs)
func3(**qwargs)
The problem with this approach is that if arg is inside qwargs, a TypeError is raised with "got multiple values for keyword argument".
I don't want to set qwargs["arg"] to default, because then func3 gets this argument without warrant. I could make a copy.copy of the qwargs and set "arg" in the copy, but qwargs could have large data structures in it and I don't want to copy them (maybe copy.copy wouldn't, only copy.deepcopy?).
What's the pythonic thing to do here?
Just build and use another dict for the purpose of calling func2, leaving the original alone for the later call to func3:
def func1(**qwargs):
d = dict(arg=default)
d.update(qwqargs)
func2(**d)
func3(**qwargs)
This is if you want a setting for arg in qwargs to override the default. Otherwise (if you want default to override any possible setting for arg in qwargs):
def func1(**qwargs):
d = dict(qwargs, arg=default)
func2(**d)
func3(**qwargs)
since the keyword-argument to dict overrides the value in the positional argument, if any.
To create a new dict with the same keys and values you can use
newdict=dict(qwargs)
If qwargs doesn't contain really many keys that's cheap.
If it's possible you could rewrite the functions to take their args really as dict instead of multiple args.