Combining several logical conditions from a list - python

I'm trying to do something that is seemingly simple: I have a list whose elements are logical expressions and I want a function that combines them into one logical expression, using a chosen logical operator (& or | is enough).
The following code does this, however, shouldn't there be a better way of doing this? It doesn't feel very Python-esque to me (main problem I see is the use of "exec", does anyone have an idea how to do it without?):
def CombineLogicalExpressions(listofexpressions,operator,outputvariableName):
''' return a condition combined from individual ones
listofexpressions = ["a == 1", "b == 2"]
operator = "and"
outputvariableName = 'myVar'
'''
#generate list from which the condition can be read:
logicalconditions = []
for expression in listofexpressions:
logicalconditions.append(expression)
logicalconditions.append(' ' + str(operator) + ' ')
del logicalconditions[-1] # delete the final operator
#create string that holds the full expression
condition = ''
for a in logicalconditions:
condition = condition + a
condition = 'FinalExpression = (' + condition + ')'
return condition
FinalExpression = False
a = 1
b = 2
condition = CombineLogicalExpressions(['a == 1', 'b == 2'] ,
'and', 'FinalExpression')
#set FinalBooleanQueryResult to the outcome of executing condition:
exec condition
print FinalExpression
You are probably wondering why I would have the logical conditions as strings. This is a simplification in the code above. In reality, I have a container object 'someContainer' and it has a method '.contains(string)' which will return a query which can be used to slice the container and give all entries whose key contains 'string':
#returns sliced someContainer with keys matching 'string'
someContainer[someContainer.contains(string)]
Now I would like to extend the functionality of 'contain()' to be able to supply a list of strings:
#returns sliced someContainer with keys matching all strings in 'listofkeywords'
containsMultiple(someContainer, listofkeywords)
I hope this is not too long and specific to put people off! I have tried searching for answers, but to my surprise couldn't find anything.

You could easily use the any() or all() builtins for this:
class Container(object):
def __init__(self, items):
self.items = items
def contains(self, s):
return s in self.items
def contains_any(some_container, items):
return any((some_container.contains(i) for i in items))
def contains_all(some_container, items):
return all((some_container.contains(i) for i in items))
c = Container(['foo', 'bar'])
print contains_any(c, ['foo', 'qux'])
print contains_all(c, ['foo', 'qux'])
print contains_all(c, ['foo', 'bar'])
Output:
True
False
True
The (some_container.contains(i) for i in items) inside the any() or all() calls is a so called generator expression. It's similar to a list comprehension, but it's lazy, possibly saving you plenty of calls to Container.contains().

In fact I found a very nice and neat solution for my problem, using the "reduce" function and the operator module. The operator module turns a binary operator into a function that takes two arguments, like:
operator.and_(A,B) equivalent to: (A and B).
Reduce will apply a function of two arguments cumulatively to a list of arguments, i.e.
reduce(function,[A,B,C]) equivalent to: function( A, function(B,C) )
With this I'll give the code which is solving the original simplified problem I gave below. Note that this, in particular, also works perfectly for the containers I am actually interested in:
def CombineLogicalExpressionsBetter(listofexpressions,operatorname):
'''
use as:
CombineLogicalExpressionsBetter([a == 1, b == 2, c == 'z'], 'and')
'''
import operator
#make it easier for users to enter operators:
if operatorname in ('and','and_') :
operatorname = operator.and_
elif operatorname in ('or','or_'):
operatorname = operator.or_
elif operatorname in ('not','not_'):
operatorname = operator.not_
else:
raise Exception("Please enter a valid operator:
'and', 'or', 'not' ... I got: " + operatorname)
#combine expression:
totalexpression = reduce(operatorname, (expression for expression in
listofexpressions))
return totalexpression

Related

python, printing longest length of string in a list

My question is to write a function which returns the longest string and ignores any non-strings, and if there are no strings in the input list, then it should return None.
my answer:
def longest_string(x):
for i in max(x, key=len):
if not type(i)==str:
continue
if
return max
longest_string(['cat', 'dog', 'horse'])
I'm a beginner so I have no idea where to start. Apologies if this is quite simple.
This is how i would do it:
def longest_string(x):
Strings = [i for i in x if isinstance(i, str)]
return(max(Strings, key=len)) if Strings else None
Based on your code:
def longest_string(x):
l = 0
r = None
for s in x:
if isinstance(s, str) and len(s) > l:
l = len(s)
r = s
return r
print(longest_string([None, 'cat', 1, 'dog', 'horse']))
# horse
def longest_string(items):
try:
return max([x for x in items if isinstance(x, str)], key=len)
except ValueError:
return None
def longest_string(items):
strings = (s for s in items if isinstance(s, str))
longest = max(strings, key=len) if strings else None
return longest
print(longest_string(['cat', 'dog', 'horse']))
Your syntax is wrong (second-to-last line: if with no condition) and you are returning max which you did not define manually. In actuality, max is a built-in Python function which you called a few lines above.
In addition, you are not looping through all strings, you are looping through the longest string. Your code should instead be
def longest_string(l):
strings = [item for item in l if type(item) == str]
if len(strings):
return max(strings, key=len)
return None
You're on a good way, you could iterate the list and check each item is the longest:
def longest_string(x)
# handle case of 0 strings
if len(x) == 0:
return None
current_longest = ""
# Iterate the strings
for i in x:
# Handle nonestring
if type(i) != str:
continue
# if the current string is longer than the longest, replace the string.
if len(i) > len(current_longest):
current_longest = i
# This condition handles multiple elements where none are strings and should return None.
if len(current_longest) > 0:
return current_longest
else:
return None
Since you are a beginner, I recommend you to start using python's built-in methods to sort and manage lists. Is the best when it comes to logic and leaves less room for bugs.
def longest_string(x):
x = filter(lambda obj: isinstance(obj, str), x)
longest = max(list(x), key=lambda obj: len(obj), default=None)
return longest
Nonetheless, you were in a good way. Just avoid using python´s keywords for variable names (such as max, type, list, etc.)
EDIT: I see a lot of answers using one-liner conditionals, list comprehension, etc. I think those are fantastic solutions, but for the level of programming the OP is at, my answer attempts to document each step of the process and be as readable as possible.
First of all, I would highly suggest defining the type of the x argument in your function.
For example; since I see you are passing a list, you can define the type like so:
def longest_string(x: list):
....
This not only makes it more readable for potential collaborators but helps enormously when creating docstrings and/or combined with using an IDE that shows type hints when writing functions.
Next, I highly suggest you break down your "specs" into some pseudocode, which is enormously helpful for taking things one step at a time:
returns the longest string
ignores any non-strings
if there are no strings in the input list, then it should return None.
So to elaborate on those "specifications" further, we can write:
Return the longest string from a list.
Ignore any element from the input arg x that is not of type str
if no string is present in the list, return None
From here we can proceed to writing the function.
def longest_string(x: list):
# Immediately verify the input is the expected type. if not, return None (or raise Exception)
if type(x) != list:
return None # input should always be a list
# create an empty list to add all strings to
str_list = []
# Loop through list
for element in x:
# check type. if not string, continue
if type(element) != str:
pass
# at this point in our loop the element has passed our type check, and is a string.
# add the element to our str_list
str_list.append(element)
# we should now have a list of strings
# however we should handle an edge case where a list is passed to the function that contains no strings at all, which would mean we now have an empty str_list. let's check that
if not str_list: # an empty list evaluates to False. if not str_list is basically saying "if str_list is empty"
return None
# if the program has not hit one of the return statements yet, we should now have a list of strings (or at least 1 string). you can check with a simple print statement (eg. print(str_list), print(len(str_list)) )
# now we can check for the longest string
# we can use the max() function for this operation
longest_string = max(str_list, key=len)
# return the longest string!
return longest_string

Python: general iterator or pure function for testing any condition across list

I would like to have a function AllTrue that takes three arguments:
List: a list of values
Function: a function to apply to all values
Condition: something to test against the function's output
and return a boolean of whether or not all values in the list match the criteria.
I can get this to work for basic conditions as follows:
def AllTrue(List, Function = "Boolean", Condition = True):
flag = True
condition = Condition
if Function == "Boolean"
for element in List:
if element != condition:
flag = False
break
else:
Map = map(Function, List)
for m in Map:
if m != condition:
flag = False
break
return flag
Since python doesn't have function meant for explicitly returning if something is True, I just make the default "Boolean". One could clean this up by defining TrueQ to return True if an element is True and then just mapping TrueQ on the List.
The else handles queries like:
l = [[0,1], [2,3,4,5], [6,7], [8,9],[10]]
AllTrue(l, len, 2)
#False
testing if all elements in the list are of length 2. However, it can't handle more complex conditions like >/< or compound conditions like len > 2 and element[0] == 15
How can one do this?
Cleaned up version
def TrueQ(item):
return item == True
def AllTrue(List, Function = TrueQ, Condition = True):
flag = True
condition = Condition
Map = map(Function, List)
for m in Map:
if m != condition:
flag = False
break
return flag
and then just call AllTrue(List,TrueQ)
Python already has built-in the machinery you are trying to build. For example to check if all numbers in a list are even the code could be:
if all(x%2==0 for x in L):
...
if you want to check that all values are "truthy" the code is even simpler:
if all(L):
...
Note that in the first version the code is also "short-circuited", in other words the evaluation stops as soon as the result is known. In:
if all(price(x) > 100 for x in stocks):
...
the function price will be called until the first stock is found with a lower or equal price value. At that point the search will stop because the result is known to be False.
To check that all lengths are 2 in the list L the code is simply:
if all(len(x) == 2 for x in L):
...
i.e. more or less a literal translation of the request. No need to write a function for that.
If this kind of test is a "filter" that you want to pass as a parameter to another function then a lambda may turn out useful:
def search_DB(test):
for record in database:
if test(record):
result.append(record)
...
search_DB(lambda rec: all(len(x) == 2 for x in rec.strings))
I want a function that takes a list, a function, and a condition, and tells me if every element in the list matches the condition. i.e. foo(List, Len, >2)
In Python >2 is written lambda x : x>2.
There is (unfortunately) no metaprogramming facility in Python that would allow to write just >2 or things like ·>2 except using a string literal evaluation with eval and you don't want to do that. Even the standard Python library tried going down that path (see namedtuple implementation in collections) but it's really ugly.
I'm not saying that writing >2 would be a good idea, but that it would be nice to have a way to do that in case it was a good idea. Unfortunately to have decent metaprogramming abilities you need a homoiconic language representing code as data and therefore you would be programming in Lisp or another meta-language, not Python (programming in Lisp would indeed be a good idea, but for reasons unknown to me that approach is still unpopular).
Given that, the function foo to be called like
foo(L, len, lambda x : x > 2)
is just
def foo(L, f=lambda x : x, condition=lambda x: x):
return all(condition(f(x)) for x in L)
but no Python programmer would write such a function, because the original call to foo is actually more code and less clear than inlining it with:
all(len(x) > 2 for x in L)
and requires you to also learn about this thing foo (that does what all and a generator expression would do, just slower, with more code and more obfuscated).
You are reinventing the wheel. Just use something like this:
>>> l = [[0,1], [2,3,4,5], [6,7], [8,9],[10]]
>>> def all_true(iterable, f, condition):
... return all(condition(f(e)) for e in iterable)
...
>>> def cond(x): return x == 2
...
>>> all_true(l, len, cond)
False
You can define a different function to check a different condition:
>>> def cond(x): return x >= 1
...
>>> all_true(l, len, b)
True
>>>
And really, having your own function that does this seems like overkill. For example, to deal with your "complex condition" you could simply do something like:
>>> l = [[0,2],[0,1,2],[0,1,3,4]]
>>> all(len(sub) > 2 and sub[0] == 5 for sub in l)
False
>>> all(len(sub) > 1 and sub[0] == 0 for sub in l)
True
>>>
I think the ideal solution in this case may be:
def AllTrue(List, Test = lambda x:x):
all(Test(x) for x in List)
This thereby allows complex queries like:
l = [[0, 1], [1, 2, 3], [2, 5]]
AllTrue(l, lambda x: len(x) > 2 and x[0] == 1)
To adhere to Juanpa's suggestion, here it is in python naming conventions and an extension of what I posted in the question now with the ability to handle simple conditions like x > value.
from operator import *
all_true(a_list, a_function, an_operator, a_value):
a_map = map(a_function, a_list)
return all( an_operator(m, a_value) for m in a_map)
l = [[0,2],[0,1,2],[0,1,3,4]]
all_true(l, len, gt, 2)
#True
Note: this works for single conditions, but not for complex conditions like
len > 2 and element[0] == 5

Filtering itertools combinations for dynamic number of constraints

I have python program and function that returns a series of rows from my MySQL database. These returned rows are filtered by a set of IDs contained in a tuple, I then use itertools and list comprehension to form 'combinations' that conform to a fixed set of constraints (the attributes of each combination must be either "all equal" or "all unique" within that combination).
I'd like to make the function dynamic for different number of IDs but I'm not sure how to filter the returned rows dynamically (without a mess of nested IF statements). Is there a way I can re-write the if/and conditions in the function below to make them dynamic for len(tuple_of_ids)?
I'm very much still a learner when it comes to python/code development so any assistance would be appreciated!
My current (psuedo-) code:
import itertools
def get_valid_combinations(tuple_of_ids):
data = get_filtered_data_from_database(valid_ids=tuple_of_ids)
# (row1, row2, row3) assumes that the tuple_of_ids has len=3. If tuple_of_ids had 4 members I'd need (row1, row2, row3, row4) etc
valid_combinations = [(row1, row2, row3) for row1, row2, row3 in list(itertools.combinations(data, 3))
if ((row1.Age == row2.Age) # All items in combination have same Age
and (row2.Age == row3.Age))
and ((row1.School != row2.School)
and (row2.School != row3.School)
and (row1.School != row3.School)) # All items in combination have different School
]
# ...etc (i.e. there may be multiple filtering criteria, but always either ("all equal" or "all different")
return valid_combinations
ids_to_search_for = ('C00001', 'C00002', 'C00003')
get_valid_combinations(tuple_of_ids = ids_to_search_for)
>>> [(<database_row_object_1>, <database_row_object_2>, <database_row_object_3>), (<database_row_object_x>, <database_row_object_y>, <database_row_object_z>),...]
As Martijn stated in the comment, you may look at doing the filtering in SQL, which is bound to be probably more efficient. If the filtering must be done in Python, the "all equal" or "all different" check could easily be done with a set comprehension:
length = len(tuple_of_ids)
valid_combinations = [tup for tup in itertools.combinations(data, length)
if len({r.Age for r in tup}) == 1
and len({r.School for r in tup}) == length]
The only overhead with doing this is that the sets are destroyed as soon as they are created, as only their lengths are needed.
On a side note, you can drop the cast to list for itertools.combinations since you don't actually need the list.
I think that passing functions by reference is a pretty pythonic way of easily adding or removing constraints from your code. This is a contrived example:
#Just an example class
class Person(object):
__slots__ = ["age","height","weight"]
def __init__(self,age,height,weight):
self.age = age
self.height = height
self.weight = weight
​
#Function to try all tests
def test_people(people,tests):
test_results = [test(people) for test in tests]
print "Passed all tests:",all(test_results)
print "Passed at least one:",any(test_results)
#Testing functions to be passed into the test_people
def first_lighter_than_second(people):
p1 = people[0]
p2 = people[1]
return True if p1.weight < p2.weight else False
def third_older_than_first(people):
p1 = people[0]
p3 = people[2]
return True if p3.age > p1.age else False
​
#Building people list
p1 = Person(24,182.1,90.5)
p2 = Person(50,170.4,83)
p3 = Person(62,150.3,67)
people = [p1,p2,p3]
​
#Building list of test functions
tests = []
tests.append(first_lighter_than_second)
tests.append(third_older_than_first)
​
#Try all tests
test_people(people,tests)
#Output
Passed all tests: False
Passed at least one: True
A downside is that you need to create lots of small functions and remember to add them to a list

Python: can a function return a string?

I am making a recursive function that slices string until it is empty. When it is empty it alternatively selects the characters and is supposed to print or return the value. In this case I am expecting my function to return two words 'Hello' and 'World'. Maybe I have got it all wrong but what I don't understand is that my function doesn't let me print or return string. I am not asking for help but I'd like some explanation :) thanks
def lsubstr(x):
a= ''
b= ''
if x == '':
return ''
else:
a = a + x[0:]
b = b + x[1:]
lsubstr(x[2:])
#print (a,b)
return a and b
lsubstr('hweolrllod')
so I changed my code to this:
def lsubstr(x):
if len(x) <1:
return x
else:
return (lsubstr(x[2:])+str(x[0]),lsubstr(x[2:])+str(x[1]))
lsubstr('hweolrllod')
and what I am trying to make is a tuple which will store 2 pairs of characters and concatenate the next ones,
the error I get is
TypeError: Can't convert 'tuple' object to str implicitly
what exactly is going wrong, I have checked in visualization, it has trouble in concatenating.
The and keyword is a boolean operator, which means it compares two values, and returns one of the values. I think you want to return a tuple instead, like this:
...
return (a, b)
And then you can access the values using the indexing operator like this:
a = lsubstr( ... )
a[0]
a[1]
Or:
word1, word2 = lsubstr( ... )

Generating evalable python code: all combinations of functions in disjunctive normal form

(A,B,C) = (100, 200, 300)
def f1(p): return p+50
def f2(p): return p*1.5
def f3(p): return p*p
vars_ = (A,B,C)
funcs_ = [f1, f2, f3]
logic_ = ["and","or"]
vol_lmt_ = [200, 300]
op_ = [">","<","="]
I want generate the assert code string for eval() to test the validity, take below one for example:
"f1(A)>200 and f1(B)>200 and f1(C)>200" # True
-^-------------^-------------^------------: funcs_
----^-------------^-------------^---------: vars_
------^-------------^-------------^-------: op_
--------^-------------^-------------^-----: vol_lmt_
------------^-------------^---------------: logic_
My questions are:
how to generate the code string I wanted based on those vars above?
how to enumerate all test logic possibility for above (A,B,C)? For example:
"f1(A)>200 and f1(B)>200 and f1(C)>200"
"f1(A)<300 and f2(B)=200 or f3(C)>200"
is it possible to replace the the name of function to the list entry when generate the code?
"f(A)>200 and f1(B)>200 and f1(C)>200"
To
"funcs_[0](A)>200 and funcs_[0](B)>200 and funcs_[0](C)>200"
This is equivalent to taking the outer/cartesian product, "summing" across the "var" dimension, and interspersing those with the outer product of logic operators. You can use itertools.product or just the normal list comprehensions. The following will work for any number of variables, functions, comparators, logic operators, and numeric thresholds. It is also easily extensible if you choose to make more complicated expressions:
#!/usr/bin/python3
from pprint import pprint as pp
from itertools import *
VARS = 'XYZ'
FUNCS = range(2)
COMPARE = '><='
LOGIC = ['and', 'or']
NUMS = [200, 300]
def listJoin(iter):
return sum(map(list,iter), [])
terms = [
[
'func[{func}]({var}){compare}{num}'.format(func=func, var=var, compare=compare, num=num)
for var in VARS
]
for func in FUNCS
for compare in COMPARE
for num in NUMS
]
def intersperse(iter, joiners):
iter = list(iter)
for tokens in product(*(joiners for _ in iter[:-1])):
yield ' '.join(listJoin(zip(iter,tokens))+[iter[-1]])
formulas = listJoin(intersperse(t, LOGIC) for t in terms)
pp(formulas)
Result:
['func[0](X)>200 and func[0](Y)>200 and func[0](Z)>200',
'func[0](X)>200 and func[0](Y)>200 or func[0](Z)>200',
'func[0](X)>200 or func[0](Y)>200 and func[0](Z)>200',
'func[0](X)>200 or func[0](Y)>200 or func[0](Z)>200',
'func[0](X)>300 and func[0](Y)>300 and func[0](Z)>300',
'func[0](X)>300 and func[0](Y)>300 or func[0](Z)>300',
'func[0](X)>300 or func[0](Y)>300 and func[0](Z)>300',
'func[0](X)>300 or func[0](Y)>300 or func[0](Z)>300',
'func[0](X)<200 and func[0](Y)<200 and func[0](Z)<200',
'func[0](X)<200 and func[0](Y)<200 or func[0](Z)<200',
'func[0](X)<200 or func[0](Y)<200 and func[0](Z)<200',
'func[0](X)<200 or func[0](Y)<200 or func[0](Z)<200',
'func[0](X)<300 and func[0](Y)<300 and func[0](Z)<300',
'func[0](X)<300 and func[0](Y)<300 or func[0](Z)<300',
'func[0](X)<300 or func[0](Y)<300 and func[0](Z)<300',
'func[0](X)<300 or func[0](Y)<300 or func[0](Z)<300',
'func[0](X)=200 and func[0](Y)=200 and func[0](Z)=200',
'func[0](X)=200 and func[0](Y)=200 or func[0](Z)=200',
'func[0](X)=200 or func[0](Y)=200 and func[0](Z)=200',
'func[0](X)=200 or func[0](Y)=200 or func[0](Z)=200',
'func[0](X)=300 and func[0](Y)=300 and func[0](Z)=300',
'func[0](X)=300 and func[0](Y)=300 or func[0](Z)=300',
'func[0](X)=300 or func[0](Y)=300 and func[0](Z)=300',
'func[0](X)=300 or func[0](Y)=300 or func[0](Z)=300',
'func[1](X)>200 and func[1](Y)>200 and func[1](Z)>200',
'func[1](X)>200 and func[1](Y)>200 or func[1](Z)>200',
'func[1](X)>200 or func[1](Y)>200 and func[1](Z)>200',
'func[1](X)>200 or func[1](Y)>200 or func[1](Z)>200',
'func[1](X)>300 and func[1](Y)>300 and func[1](Z)>300',
'func[1](X)>300 and func[1](Y)>300 or func[1](Z)>300',
'func[1](X)>300 or func[1](Y)>300 and func[1](Z)>300',
'func[1](X)>300 or func[1](Y)>300 or func[1](Z)>300',
'func[1](X)<200 and func[1](Y)<200 and func[1](Z)<200',
'func[1](X)<200 and func[1](Y)<200 or func[1](Z)<200',
'func[1](X)<200 or func[1](Y)<200 and func[1](Z)<200',
'func[1](X)<200 or func[1](Y)<200 or func[1](Z)<200',
'func[1](X)<300 and func[1](Y)<300 and func[1](Z)<300',
'func[1](X)<300 and func[1](Y)<300 or func[1](Z)<300',
'func[1](X)<300 or func[1](Y)<300 and func[1](Z)<300',
'func[1](X)<300 or func[1](Y)<300 or func[1](Z)<300',
'func[1](X)=200 and func[1](Y)=200 and func[1](Z)=200',
'func[1](X)=200 and func[1](Y)=200 or func[1](Z)=200',
'func[1](X)=200 or func[1](Y)=200 and func[1](Z)=200',
'func[1](X)=200 or func[1](Y)=200 or func[1](Z)=200',
'func[1](X)=300 and func[1](Y)=300 and func[1](Z)=300',
'func[1](X)=300 and func[1](Y)=300 or func[1](Z)=300',
'func[1](X)=300 or func[1](Y)=300 and func[1](Z)=300',
'func[1](X)=300 or func[1](Y)=300 or func[1](Z)=300']
Maybe this can summaries what you are trying to do (using python2 syntax):
import itertools
arguments = ('A', 'B', 'C', 'D')
funcs_ = [f1, f2, f3, f4]
logic_ = ["and","or"]
op_ = [">","<","="]
vol_lmt_ = [200, 300]
num_func = len(funcs_)
assert num_func == len(arguments), ("The number of argument should be the same as "
"the number of function.")
operands = itertools.product(["funcs_[%d]" % i for i in range(num_func)],
arguments,
op_,
vol_lmt_)
def comp(operands):
templ = "{func}({arg}){op}{val}"
for operand in operands:
yield templ.format(func=operand[0], arg=operand[1],
op=operand[2], val=operand[3])
new_operands = map(comp, itertools.tee(operands, num_func))
# construct the argument to pass to itertools.product.
args = []
for operand in new_operands:
args.append(operand)
args.append(logic_)
args.pop() # Remove the last logic operator.
res = itertools.product(*args)
print " ".join(res.next())
# funcs_[0](A)>200 and funcs_[0](A)>200 and funcs_[0](A)>200 and funcs_[0](A)>200
...
In this method i just cheated by replacing vars_ with ('A', 'B', 'C'). beside that i think it should work.
If you don't like my way of cheating by hard coding the the vars_ list and the funcs_ name you can get the name of your variable from the globals dictionary something like this:
def get_name(obj):
"""Get the name of an object (variable) from the globals dict.
Argument:
- obj : The variable that we want to get the name of.
Return:
- A string representing the name of the object if it was found else return None.
"""
for name, value in globals().items():
if value is obj:
return name
First of all, I would start by saying eval is a bad idea.There is always another way to do it.
Answer to your question:
Question 1:
Function name,
You can get using f.func_name.
Variable name,
Not so simple,but this should work,
import gc, sys
def find_names(obj):
frame = sys._getframe()
for frame in iter(lambda: frame.f_back, None):
frame.f_locals
result = []
for referrer in gc.get_referrers(obj):
if isinstance(referrer, dict):
for k, v in referrer.iteritems():
if v is obj:
result.append(k)
return result
a = 97
print find_names(a)[0]
It doesn't matter if it returns the wrong name since their value will be equal.
The operator and vol_limit is easily generated.
2nd Question.
No obvious solution out of mind. Iterate through all of them?
3rd Question.
Yes it is possible.
Check out Decorators.

Categories