When a function accepts a function argument (or a class has a function slot), there is a choice between two approaches:
def foo(..., my_func=None, ...):
...
if my_func:
my_func(...)
...
and
def foo(..., my_func=(lambda ...: None), ...):
...
my_func(...)
...
What is more Pythonic/clear/readable?
What is faster - an extra boolean check or a trivial function call?
When using this:
>>> def bar():
... print("Goodbye, World!")
...
I find this very readable:
>>> def foo(my_func = lambda : None):
... my_func()
...
>>> foo()
>>> foo(bar)
Goodbye, World!
I find this pointlessly annoying
>>> def baz(my_func = None):
... if my_func is not None:
... my_func()
...
>>> baz()
>>> baz(bar)
Goodbye, World!
Try to keep None checks out of your life. Use None when you want it to do what it does well: blow up in your face. Don't ask it to be quiet. One way or another it's going to create annoying noise if you use it.
What is faster - an extra boolean check or a trivial function call?
Why, in Gods name, do you care?
For the record, I find this readable but overly permissive:
>>> def buz(my_func = lambda **k:None):
... my_func()
...
>>> buz(bar)
Goodbye, World!
Related
I'm having some trouble dealing with the nested tuple which Mock.call_args_list returns.
def test_foo(self):
def foo(fn):
fn('PASS and some other stuff')
f = Mock()
foo(f)
foo(f)
foo(f)
for call in f.call_args_list:
for args in call:
for arg in args:
self.assertTrue(arg.startswith('PASS'))
I would like to know if there is a better way to unpack that call_args_list on the mock object in order to make my assertion. This loop works, but it feels like there must be a more straight forward way.
I think that many of the difficulties here are wrapped up in the treatment of the "call" object. It can be thought of as a tuple with 2 members (args, kwargs) and so it's frequently nice to unpack it:
args, kwargs = call
Once it's unpacked, then you can make your assertions separately for args and kwargs (since one is a tuple and the other a dict)
def test_foo(self):
def foo(fn):
fn('PASS and some other stuff')
f = Mock()
foo(f)
foo(f)
foo(f)
for call in f.call_args_list:
args, kwargs = call
self.assertTrue(all(a.startswith('PASS') for a in args))
Note that sometimes the terseness isn't helpful (e.g. if there is an error):
for call in f.call_args_list:
args, kwargs = call
for a in args:
self.assertTrue(a.startswith('PASS'), msg="%s doesn't start with PASS" % a)
A nicer way might be to build up the expected calls your self then use a direct assertion:
>>> from mock import call, Mock
>>> f = Mock()
>>> f('first call')
<Mock name='mock()' id='31270416'>
>>> f('second call')
<Mock name='mock()' id='31270416'>
>>> expected_calls = [call(s + ' call') for s in ('first', 'second')]
>>> f.assert_has_calls(expected_calls)
Note that the calls must be sequential, if you don't want that then override the any_order kwarg to the assertion.
Also note that it's permitted for there to be extra calls before or after the
specified calls. If you don't want that, you'll need to add another assertion:
>>> assert f.call_count == len(expected_calls)
Addressing the comment of mgilson, here's an example of creating a dummy object that you can use for wildcard equality comparisons:
>>> class AnySuffix(object):
... def __eq__(self, other):
... try:
... return other.startswith('PASS')
... except Exception:
... return False
...
>>> f = Mock()
>>> f('PASS and some other stuff')
<Mock name='mock()' id='28717456'>
>>> f('PASS more stuff')
<Mock name='mock()' id='28717456'>
>>> f("PASS blah blah don't care")
<Mock name='mock()' id='28717456'>
>>> expected_calls = [call(AnySuffix())]*3
>>> f.assert_has_calls(expected_calls)
And an example of the failure mode:
>>> Mock().assert_has_calls(expected_calls)
AssertionError: Calls not found.
Expected: [call(<__main__.AnySuffix object at 0x1f6d750>),
call(<__main__.AnySuffix object at 0x1f6d750>),
call(<__main__.AnySuffix object at 0x1f6d750>)]
Actual: []
I'd like to create a __str__ method that creates the string in various formats according to user choice.
The best I have come up with is to make a __str__(**kwargs) method, and this seems to work ok, but it isn't compatible with str(obj) or print(obj). In other words I have to use print(obj.__str__(style='pretty')) rather than print(obj, style='pretty').
Implement the object.__format__() method instead, and a user can then specify the formatting required with the format() function and str.format() method:
print(format(obj, 'pretty'))
or
print('This object is pretty: {:pretty}'.format(obj))
You probably want to delegate most of the handling of the format on to str.__format__:
def __format__(self, spec):
if spec.endswith('pretty'):
prettified = self.pretty_version()
return prettified.__format__(spec[:-6])
return str(self).__format__(spec)
That way you can still support all the field width and padding alignment options that the default str.__format__ method supports.
Demo:
>>> class Foo():
... def __str__(self):
... return 'plain foo'
... def pretty_version(self):
... return 'pretty foo'
... def __format__(self, spec):
... if spec.endswith('pretty'):
... prettified = self.pretty_version()
... return prettified.__format__(spec[:-6])
... return str(self).__format__(spec)
...
>>> f = Foo()
>>> print(f)
plain foo
>>> print(format(f))
plain foo
>>> print(format(f, 'pretty'))
pretty foo
>>> print(format(f, '>20pretty'))
pretty foo
>>> print('This object is pretty: {:^20pretty}!'.format(f))
This object is pretty: pretty foo !
>>> def hehe():
... return "spam"
...
>>> repr(hehe)
'<function hehe at 0x7fe5624e29b0>'
I want to have:
>>> repr(hehe)
'hehe function created by awesome programmer'
How do I do that? Putting __repr__ inside hehe function does not work.
EDIT:
In case you guys are wondering why I want to do this:
>>> defaultdict(hehe)
defaultdict(<function hehe at 0x7f0e0e252280>, {})
I just don't like the way it shows here.
No, you cannot change the representation of a function object; if you wanted to add documentation, you'd add a docstring:
def foo():
"""Frob the bar baz"""
and access that with help(foo) or print foo.__doc__.
You can create a callable object with a custom __repr__, which acts just like a function:
class MyCallable(object):
def __call__(self):
return "spam"
def __repr__(self):
return 'hehe function created by awesome programmer'
Demo:
>>> class MyCallable(object):
... def __call__(self):
... return "spam"
... def __repr__(self):
... return 'hehe function created by awesome programmer'
...
>>> hehe = MyCallable()
>>> hehe
hehe function created by awesome programmer
>>> hehe()
'spam'
Usually, when you want to change something about the function, say function signature, function behavior or function attributes, you should consider using a decorator. So here is how you might implement what you want:
class change_repr(object):
def __init__(self, functor):
self.functor = functor
# lets copy some key attributes from the original function
self.__name__ = functor.__name__
self.__doc__ = functor.__doc__
def __call__(self, *args, **kwargs):
return self.functor(*args, **kwargs)
def __repr__(self):
return '<function %s created by ...>' % self.functor.__name__
#change_repr
def f():
return 'spam'
print f() # spam
print repr(f) # <function hehe created by ...>
Note, that you can only use class based decorator, since you need to override __repr__ method, which you can't do with a function object.
Not directly the answer to your question, but perhaps you really want a docstring?
>>> def hehe():
... '''hehe function created by awesome programmer'''
... return 'spam'
...
>>> help(hehe)
Help on function hehe in module __main__:
hehe()
hehe function created by awesome programmer
Here's a slightly more flexible version of what's in Alexander Zhukov's answer:
def representation(repr_text):
class Decorator(object):
def __init__(self, functor):
self.functor = functor
def __call__(self, *args, **kwargs):
return self.functor(*args, **kwargs)
def __repr__(self):
return (repr_text % self.functor.__name__ if '%' in repr_text
else repr_text)
return Decorator
from collections import defaultdict
#representation('<function %s created by awesome programmer>')
def f():
return list
dd = defaultdict(f)
print repr(dd)
Output:
defaultdict(<function f created by awesome programmer>, {})
Sincerepresentation()returns a decorator, if you wanted the same boilerplate on several functions you could do something like this:
myrepr = representation('<function %s created by awesome programmer>')
#myrepr
def f():
...
#myrepr
def g():
...
etc
I'm using Michael Foord's mock library and have a question about it.
I want to mock a property, so I do this:
eggs = mock.PropertyMock(return_value='eggs')
spam = mock.Mock()
type(spam).eggs = eggs
assert spam.eggs == 'eggs'
This works brilliantly. However I find the type() part ugly and would love to do something like this:
eggs = mock.PropertyMock(return_value='eggs')
spam = mock.Mock(eggs = eggs)
assert spam.eggs == 'eggs'
The last example doesn't work as expected, spam.eggs becomes a method instead of a property.
I know I can use mock.Mock(eggs = 'eggs') so eggs is not a method, but I want to be able to assert the property. :-)
I am using Python 2.7, but I assume unittest.Mock works too.
The patch can help you to a degree, the code is taken from official Mock document
>>> class Foo(object):
... #property
... def foo(self):
... return 'something'
... #foo.setter
... def foo(self, value):
... pass
...
>>> with patch('__main__.Foo.foo', new_callable=PropertyMock) as mock_foo:
... mock_foo.return_value = 'mockity-mock'
... this_foo = Foo()
... print this_foo.foo
... this_foo.foo = 6
...
mockity-mock
>>> mock_foo.mock_calls
[call(), call(6)]
How can we find all the functions in a python program??? for eg.
Input
def func1:
#doing something
def func2:
#doing something
def func3:
#doing something
Output
{'func1' , 'func2' , 'func3'}
If you want all functions in the global scope, you can use globals() with inspect.isfunction():
>>> def foo():
... pass
...
>>> def bar():
... pass
...
>>> import inspect
>>> [member.__name__ for member in globals().values() \
... if inspect.isfunction(member)]
['bar', 'foo']
Guessing you want only the methods in your current context:
import inspect
d = locals()
funcs = [f for f in d if inspect.isfunction(d[f])]