Creating a Python Object from a String in Python 3 - python

This is not a duplicate of creating a function object from a string because that is a Python 2 solution with exec not as a function()
Trying to implement that solution in Python 3 gets this:
d = {}
exec("def f(x): return x")in d
print(d)
returns:
{}
So the question is, how do I create a function in Python 3 from an arbitrary string? (In my case read in from a YAML file, but that's a side issue.)

X in d , returns True if X is found in element d.
Your exec call is defining function f in global scope.
This appears to do what you want it to:
>>> d = {}
>>> exec("def f(x): return x", d)
>>> d["f"]("Hello World")
'Hello World'

>>> d={}
>>> exec("def f(x): return x",None,d)
>>> d['f'](2)
2
>>>

Related

applying list of functions to list of arguments in python

I have the following lists
fncs = ["MyLinkedList","addAtHead","get","addAtTail"]
args = [[],[8],[1],[81]]
And I want to return
[MyLinkedList(), addAtHead(8), get(1), addAtTail(81)]
I thought I could use fnc_vals = [f(x) for f, x in zip(fncs, args)] but that doesn't seem to work since my fncs list is a list of strings. How can I apply a list of functions to a list of arguments (in Python)?
If you have a list of strings refering to the current scope functions you can use globals or locals:
fnc_vals = [golbals()[f](x) for f, x in zip(fncs, args)]
Check this example:
>>> def foo(x):
... return x
...
>>> globals()["foo"](10)
10
You can also build your own functions addressing dictionary:
>>> def foo(x):
... return x
...
>>> def bar(x):
... return x + 10
...
>>> func_dict = {f.__name__:f for f in (foo, bar)}
>>> func_dict["foo"](10)
10
If the functions are in the local namespace, just remove the quotes:
fncs = [MyLinkedList, addAtHead, get, addAtTail]
args = [[], [8], [1], [81]]
If the 1st list must be strings, you can get the function objects with:
function_names = ["MyLinkedList", "addAtHead", "get", "addAtTail"]
functions = [locals()[fn] for fn in function_names]
If, that is, the functions are named in the local namespace.

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.

Execute a function randomly

Consider the following functions:
def a():
print "a"
def b():
print "b"
Is there a way to pick a function to run randomly? I tried using:
random.choice([a(),b()])
but it returns both functions, I just want it to return one function.
Only call the selected function, not both of them:
random.choice([a,b])()
Below is a demonstration:
>>> import random
>>> def a():
... print "a"
...
>>> def b():
... print "b"
...
>>> random.choice([a,b])()
a
>>> random.choice([a,b])()
b
>>>
Your old code called both functions when the list [a(),b()] was created, causing Python to print both a and b. Afterwards, it told random.choice to choose from the list [None, None]1, which does nothing. You can see this from the demonstration below:
>>> [a(),b()]
a
b
[None, None]
>>>
The new code however uses random.choice to randomly select a function object from the list [a,b]:
>>> random.choice([a,b])
<function b at 0x01AFD970>
>>> random.choice([a,b])
<function a at 0x01AFD930>
>>>
It then calls only that function.
1Functions return None by default. Since a and b lack return-statements, they each return None.
Is it what you want?
random.choice([a,b])()

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.

Python Store dynamic data

I don't know if the heading makes sense... but this is what I am trying to do using list
>>> x = 5
>>> l = [x]
>>> l
[5]
>>> x = 6
>>> l
[5] # I want l to automatically get updated and wish to see [6]
>>>
The same happens with dict, tuple. Is there a python object that can store the dynamic value of variable?
Thanks,
There's no way to get this to work due to how the assignment operator works in Python. x = WHATEVER will always rebind the local name x to WHATEVER, without modifying what previously x was previously bound to.(*)
You can work around this by replacing the integers with a container data type, such as single-element lists:
>>> x = [5]
>>> l = [x]
>>> l
[[5]]
>>> x[0] = 6
>>> l
[[6]]
but that's really a hack, and I wouldn't recommend it for anything but experimentation.
(*) Rebinding may actually modify previously bound objects when their reference count drops to zero, e.g. it may close files. You shouldn't rely on that, though.
A variable is a place to store data. A datastructure is a place to store data. Pick the one which meets your needs.
You can do it with the numpy module.
>>> from numpy import array
>>> a = array(5)
>>> a
array(5)
>>> l = [a]
>>> l
[array(5)]
>>> a.itemset(6)
>>> a
array(6)
>>> l
[array(6)]
Generally a 0-D numpy array can be treated as any regular value as shown below:
>>> a + 3
9
However, if you need to, you can access the underlying object as such:
>>> a.item()
6
Here's a kind of hacky method of dynamic access that isn't very extensible/flexible in its given form, but could be used as a basis for something better.
>>> a = 7
>>> class l:
def a_get(self):
global a
return a
def a_set(self, value):
global a
a = value
a = property(a_get, a_set)
>>> c = l()
>>> c.a
7
>>> a = 4
>>> c.a
4
>>> c.a = 6
>>> a
6

Categories