Determining the method called within a lambda function - python

I have a lambda function which is passed to a object and stored as a variable:
f = lambda x: x.method_foo()
I want to determine the name of method called on the variable x as a string. So I want
method_foo
saved as a string.
Any help appreciated.

You could access the lambda's code object with func_code, and access the code's local names with co_names.
>>> f = lambda x: x.method_foo
>>> f.func_code.co_names
('method_foo',)
>>> f.func_code.co_names[0]
'method_foo'

This is a bit "crazy", but you can use pass a Mock to f and get the method that was added to the mock after calling the function:
>>> from mock import Mock
>>> f = lambda x: x.method_foo
>>> m = Mock()
>>> old_methods = dir(m)
>>> f(m)
<Mock name='mock.method_foo' id='4517582608'>
>>> new_methods = dir(m)
>>> next(method for method in new_methods if method not in old_methods)
'method_foo'

Related

python - Overloading operators on the fly

I would like to know, if there is a way to overload operators in Python in runtime. For instance:
class A:
pass
a = A()
a.__str__ = lambda self: "noice"
print(str(a))
The desired output is "noice", but the given code uses object's implementation of the str function instead, yielding something along the lines: <__main__.A object at 0x000001CAB2051490>.
Why doesn't the code use my overriden implementation of the function overload?
Python version used is 3.9.2.
When you call str(a), it resolves to the equivalent of a.__class__.__str__(a), not a.__str__().
>>> A.__str__ = lambda self: "noice"
>>> str(a)
'noice'
You have to assign that function to the class, not an instance of the class.
>>> class A:
... pass
...
>>> a = A()
>>> a.__str__ = lambda x: 'hi'
>>> print(a)
<__main__.A object at 0x000000A4D16C1D30>
>>> A.__str__ = lambda x: 'hi'
>>> print(a)
hi

What is the Python equivalent of LINQ OfType<T>() (in .NET)

I am trying to get a single Handler of a specific custom type MemoryListHandler in the logger.handlers collection.
With .NET I would simply use the following LINQ extension, which filters element and returns only those of type MemoryListHandler:
logger.handlers.OfType<MemoryListHandler>().SingleOrDefault()
What would be the most elegant equivalent in Python?
My current (not very neat) attempt is:
next((handler for handler in logger.handlers if handler is MemoryListHandler), None)
You might try the index method.
try:
lh = logger.handlers
x = lh[lh.index(MemoryListHandler)]
except ValueError:
x = some_default_value
Python is dynamically typed, therefore you might not need to convert anything.
However, in some cases you still might need to convert, say, int to string :
map(lambda x: str(x), [1, 2, 3])
Or, given your function accepts only one argument, just pass the function alone :
map(str, [1, 2, 3])
Update
filter(lambda x: type(x) == YourClass, [your_array])
For Python the is operator tests identity NOT type like it does in c#. You want isinstance for your test -- which will also work with subtypes of the target_type you're looking for.
Using the Python REPL to illustrate the difference between is and isinstance:
>>> s = ""
>>> s is str
False
>>> isinstance(s, str)
True
>>> class Foo:
... def __init__(self):
... pass
...
>>> f = Foo()
>>> g = Foo()
>>> f is g
False
>>> f is Foo
False
>>> g is Foo
False
>>> x = f
>>> f is x
True
>>> g is x
False
Your own expression is pretty close to what you want. You can hide it behind a method:
def first_of_type(xs, target_type):
return next((x for x in xs if isinstance(x, target_type)), None)
Usage becomes short and sweet:
first_of_type(logger.handlers, MemoryListHandler)
Note: addition of type hints and doc comments would help usability.

Altering the definition of a function without an assignment

I was given this task:
Write a one-line expression that transforms an f(x) function into f(x)
+1. Hint: think about how a local frame binding for saved value of f, can be created without an assignment.
Example:
>>> f = lambda x: x*x
>>> f(5) 25
>>> ---your one line expression---
>>> f(5) 26
>>> f, g = None, f
>>> g(5) 26
I tried to do this:
k,f=f, lambda x: k(x)+1
And it works but it uses the assignment f=f. How could I do this without an assignment?
My teacher told me that there is a function in Python similar to the let function in Scheme, but I'm not sure what this function is that she wants us to use because she did not provide the name of the function.
This is not something that should be used in general, but I suppose you could do this:
def f(x, f=f): return f(x) + 1
And there's "no (explicit) assignments" since we're just defining a new function name which happens to be the same as the original.
This will work, but it may be cheating:
>>> f = lambda x: x*x
>>> f(5)
25
>>> globals().update({'f': (lambda g: lambda x: g(x)+1)(f)})
>>> f(5)
26
>>> f, g = None, f
>>> g(5)
26

How to test that functools.partial produces the expected function object

When going from one API to another it can sometimes be helpful to map between similar keywords in each API, allowing one controller API to flexibly dispatch to other libraries without needing the user to fuss around with the different API's under the hood.
Assume some library, other_api, has a method called "logarithm", and the keyword argument for the base is something I need to factor out of my code, like "log_base_val"; so that to use it from other_api I need to type (for example):
other_api.logarithm(log_base_val=math.e)
Consider a toy class like this:
import other_api
import math
import functools
class Foo(object):
_SUPPORTED_ARGS = {"base":"log_base_val"}
def arg_binder(self, other_api_function_name, **kwargs):
other_api_function = getattr(other_api, other_api_function_name)
other_api_kwargs = {_SUPPORTED_ARGS[k]:v for k,v in kwargs.iteritems()}
return functools.partial(other_api_function, **other_api_kwargs)
With Foo, I can map some other API, where this argument is always called base, like this:
f = Foo()
ln = f.arg_binder("logarithm", base=math.e)
and ln is logically equivalent to (with log_base_val=math.e in kwargs, from functools):
other_api.logarithm(*args, **kwargs)
However, manually making the same argument bind by invoking functools will lead to different function objects:
In [10]: import functools
In [11]: def foo(a, b):
....: return a + b
....:
In [12]: f1 = functools.partial(foo, 2)
In [13]: f2 = functools.partial(foo, 2)
In [14]: id(f1)
Out[14]: 67615304
In [15]: id(f2)
Out[15]: 67615568
So testing for f1 == f2 won't succeed as intended:
In [16]: f1 == f2
Out[16]: False
So the question is: what is the prescribed way to test whether the argument binding function has resulted in the correct output function object?
The func attribute on the partial() object is a reference to the original function object:
f1.func is f2.func
Function objects themselves don't implement a __eq__ method, so you may as well just use is to test for identity.
Similarly, the partial().args and partial().keywords contain the arguments and keyword arguments to be passed to the function when called.
Demo:
>>> from functools import partial
>>> def foo(a, b):
... return a + b
...
>>> f1 = partial(foo, 2)
>>> f2 = partial(foo, 2)
>>> f1.func is f2.func
True
>>> f1.args
(2,)
>>> f2.args
(2,)
>>> f1.keywords is None
True
>>> f2.keywords is None
True

python - how can I dynamically create a function with a name based on a string read in from a file?

Let's say I have a file containing the string "unpredictable_words". I would like to read in this string and then define a function as follows:
def test_unpredictable_words(self):
do_important_stuff()
I would then like to inject this function into a class definition so that this function can be called on any instances of this class.
How can I accomplish this?
I looked a bit at this answer - https://stackoverflow.com/a/8160676/1701170 - but I don't think it does what I want, exactly, or at least I can't understand what is going on.
Python 2.7.3 (default, Sep 26 2012, 21:51:14)
>>> def injected(self):
... print 'injected'
...
>>> class A(object):
... pass
...
>>> A.injected = injected
>>> a = A()
>>> a.injected()
injected
>>> def func2(self):
... print 'func2'
...
>>> setattr(A, 'injected2', func2)
>>> a.injected2()
func2
>>>
You don't need to define a function under one true name. Functions are first-class entitiens, you can pass them around and assign to variables. On top level, you use globals(), withing another function, locals() to bind a name:
>>> def foo(x):
... return x + 1
...
>>> name = 'unpredictable_words'
>>>
>>> globals()['test_' + name] = foo
>>>
>>> test_unpredictable_words(1)
2
>>>
>>> def some_function():
... locals()['test_' + name] = foo
... return test_unpredictable_words(1)
...
>>> some_function()
2
>>>
Sometimes you still want that the function knows its name, in order to appear nicely in a stacktrace. Now test_unpredictable_words appear as foo in error messages. This is not easy to fix, since that name is stored in foo.func_code.co_name and can't be changed.

Categories