accept unevaluated logical expression as argument, defer execute - python

target code:
test_box = TestBox(Checkers.begin_with("op") and Checkers.end_with("or"))
test_box.run("operator") # True
test_box.run("option") # False
What I think(may be in the wrong way): TestBox may be a class or a method, and begin_with and end_with are classmethod of class Checkers, but how to make Checkers.begin_with("op") and Checkers.end_with("or") evaluated until test_box.run() was called?

I have found a solution which use lambda, post here:
class TestBox:
def __init__(self, func):
self._func = func
def run(self, string):
Checkers.string = string
return self._func()
class Checkers:
string = None
#classmethod
def begin_with(cls, val):
return cls.string.startswith(val)
#classmethod
def end_with(cls, val):
return cls.string.endswith(val)
if __name__ == '__main__':
test_box = TestBox(lambda: Checkers.begin_with("op") or Checkers.end_with("or"))
print(test_box.run("operator")) # True
print(test_box.run("xxtion")) # False
print(test_box.run("xxtionor")) # True

Related

Python Classes Understand methods

I have simple task: we have class TestingClass and we wanna simply test his methods. And we have class TestHelper for testing purpose.
class TestingClass():
def testing_method_1(self):
return False
def testing_method_2(self):
return True
class TestHelper():
def __init__(self, class_name):
pass
def add(self, func_name, func_result):
pass
def run(self):
pass
helper = TestHelper(TestingClass)
helper.add(“testing_method_1”, False)
helper.add(“testing_method_2”, True)
result = helper.run()
my target implement methods for class TestHelper . I solved it for myself but I think its bad realization. I initialize empty dictionary and test class. Next I add every method and test method result to dictionary. In run method I compare results.
class TestHelper():
def __init__(self, class_name):
self.test_class = class_name()
self.func_list = {}
def add(self, func_name, func_result):
temp = 'self.test_class.' + func_name
self.func_list[temp] = func_result
def run(self):
for f in self.func_list.keys():
if eval(f)() == self.func_list[f]:
print('yes')
else:
print('no')
Can I resolve it in best way? Thanks!
Using eval for this purpose is overkill.
You could instead use the getattr() function to retrieve the function and call it.
Read more: Python Docs
class TestHelper():
def __init__(self, class_name):
self.test_class = class_name()
self.func_list = {}
def add(self, func_name, func_result):
# { <function>:<desired result> }
self.func_list[func_name] = func_result
def run(self):
for func, desired_result in self.func_list.items():
if getattr(self.test_class, func)() is desired_result:
print('yes')
else:
print('no')
This code produces results:
...
>>> helper = TestHelper(TestingClass)
>>> helper.add("testing_method_1", False)
>>> helper.add("testing_method_2", True)
>>> result = helper.run()
yes
yes
Of course you should also test if the class even has an attribute with the given function name. You can use hasattr() for this.

Passing a method argument to a class

I have the following callable:
class SomeClass(object):
def __init__(self, expr, return_status):
self._expr = expr
self._status = return_status
def __call__(self):
if self._expr == self._status:
return True
def __str__(self):
return ("Function: %s\n Return Status: %s\n" %
(self.__class__.__name__, self._status))
The problem I am facing is this that whenever I try to pass an expression like:
some_variable = SomeFunction(SomeClass.some_method,return_status=True)
SomeClass.some_method gets evaluated and gets stored in self._expr as a boolean value.
What I actually want is this expression (SomeClass.some_method) be stored in self._expr and get evaluated each time the __call__(self) method is called.
Am I making sense?
Let's say I am taking the following example:
def addition(c,b):
print "'addition' function called!\n"
sum = c+b
if sum>5:
return True
else:
return False
script_timeout = 3
some_variable = SomeFunction(addition(1,2),return_status=True)
print "some_variable: \n%s" %some_variable
some_class.some_method(some_variable, script_timeout, 1)
This gives me the following output:
'addition' function called!
SomeFunction (_init_) function called!
expr: False
self._expr = False and self._status = True
SomeFunction (_str_) function called!
self.__class__.__name__ = SomeFunction and self._expr = False
monitor:
Function: SomeFunction
Return Status of the Expression: True
SomeFunction (_call_) function called!
self._expr = False and self._status = True
SomeFunction (_call_) function called!
self._expr = False and self._status = True
SomeFunction (_call_) function called!
self._expr = False and self._status = True
So, the concern is the addition function is not getting called with each iteration calling of SomeFunction (by the some_method method.)
The required functionality is this that SomeFunction (when called by some_method) should call the function addition.
Assuming expr will be a method/function and assuming you know what method/function returns, you have 3 options. Follow just one of these 3 options and you'll achieve what you want.
1) You can call expr in the assignement to self.expr:
....
class CheckStatus:
def __init__(self, expr, ...)
self.expr = expr() # expr() being called here, store whatever the result is to self.expr
def __call__(self):
# self.expr already holds a boolean value, or anything your expr returns
if self.expr == self.status:
# self.expr match ...
# do what else you have to do
obj = CheckStatus(SomeClass().method, ...) # pay attention how we pass the method here
2) If self.expr is a reference to that expr, then:
class CheckStatus:
def __init__(self, expr, ...):
self.expr = expr
def __call__(self):
# in this example, self.expr now it's a reference to some method
# thus you need to call self.expr here
if self.expr() == self.status:
....
obj = CheckStatus(SomeClass().method, ...) # pay attention how we pass method for this example
3) call the SomeClass().method() at instantiation of CheckStatus():
class CheckStatus:
def __init__(self, expr, ...):
self.expr = expr # for this example, expr already is a boolean or anything else some method/function returned
def __call__(self):
# don't need to call anything here
if self.expr == self.status:
....
obj = CheckStatus(SomeClass().method(), ...) # because here we called SomeClass().method()
You have to call the method/function your passing in to your CheckStatus class somewhere, otherwise you'll never have that method/function result to check.
Hope it was clear.
class S(object):
def __init__(self, expr, return_status):
self._expr = expr
self._status = return_status
def __call__(self):
if self._expr() == self._status:
raise Exception
self._expr()
def __str__(self):
return ("Function: %s\n Return Status of the Expression: %s\n" %
(self.__class__.__name__, self._status))
def some_method():return True
try:
S(some_method,return_status=True)()
except Exception as e:
print('Got Exception')

Getting decorated methods of a given class from within that class

Given a class and a set of its methods - how can you determine from within that class which methods have been decorated with a certain decorator?
My goal is to basically get the actual values of the methods that are decorated, so something like:
class A():
def get_values(self):
...
# returned {'a-special-name': 1, 'b': 2}
#my_dec('a-special-name') # Ideally be able to also put optional name
def a(self):
return 1
#my_dec
def b(self):
return 2
Any idea on how to accomplish this?
Edit: this should also work on parent classes, that is, if A is a subclass of:
class B():
#my_dec
def c(self):
return 3
then get_values() of A instance should return {'a-special-name': 1, 'b': 2, 'c': 3} (order is irrelevant of course)
Edit: class based decorator that works but not with inheritance. Any idea how to make it work with inheritance but without having to decorate the class itself?
class my_dec(object):
def __init__(self, func, name=None):
self.func = func
self.name = name or func.__name__
self.func._some_flag = True
def __get__(self, instance, cls=None):
if instance is None:
return self
return self.func(instance)
If you can define the decorator yourself, then simply have it "mark" the method object in some way:
def my_dec(method):
method._this_be_decorated = True
return method
The class can then look for those marked methods; something like:
from inspect import isfunction
class A:
def get_values(self):
return filter(lambda i: isfunction(i) and hasattr(i, '_this_be_decorated'),
vars(type(self)).values())
This will return an iterable of function objects which you can process further as needed.
def my_dec(name):
if callable(name):
# name is callable – take its name
func = name # no make the code more readable
func.special_name = func.__name__
return func
else:
# name is the name to give – add an inner layer of functions
def inner(function_object):
function_object.special_name = name
return function_object
return inner
class A():
def get_values(self):
# return a dict of special name to call result mapping for every class member that has a special_name.
return {func.special_name: func(self) for func in self.__class__.__dict__.values() if hasattr(func, 'special_name')}
# returned {'a-special-name': 1, 'b': 2}
#my_dec('a-special-name') # Ideally be able to also put optional name
def a(self):
return 1
#my_dec
def b(self):
return 2
def no_dec(self):
return 42
should do what you want.
As deceze mentions, decorators can do whatever they want so there's no reliable generic answer. If you "own" the decorator you can add special properties to it's return value ie (Q&D py2.7 example):
def mydec(name=''):
# py27 hack - for py3 you want nonlocal instead
n = [name]
def innerdec(func):
# py27 hack - for py3 you want nonlocal instead
name = n[0] or func.__name__
def wrapper(*args, **kw):
print("in mydec.wrapper for {}".format(name))
return func(*args, **kw)
wrapper.ismydec = True # so we know this is decorated by mydec
wrapper.func = func # so we can get the original func
wrapper.name = name
return wrapper
return innerdec
def collect_dec(cls):
decorated = {}
for attname in dir(cls):
obj = getattr(cls, attname)
if getattr(obj, "ismydec", False):
decorated[obj.name] = obj.func
cls._decorated_funcs = decorated
return cls
#collect_dec
class A():
def get_values(self):
return {
name:func(self) for name, func in self._decorated_funcs.items()
}
#mydec('a-special-name') # Ideally be able to also put optional name
def a(self):
return 1
#mydec() # no name
def b(self):
return 2
a = A()
print(a.get_values())
Which outputs:
{'a-special-name': 1, 'b': 2}

How to seperate ' test(a =10)' and 'test' in python

I want to do this:
a = TestClass1() <br>
a.test.fun() #==> this i want to call TestClass2 method fun() <br>
a.test(a=10).fun() #===> this i want to call TestClass3 method fun() <br>
Does anyone know how to separate this?
I have three classes:
class TestClass1:
aa = ""
def __init__(self):
self.aa = "ccc"
def __getattr__(self, item):
print("test 1 get attr = ",item)
return TestClass2() or TestClass3() #==> I don't how to seperate test and test(a =10)
def __getitem__(self, item):
print("__getitem__",item)
class TestClass2:
def __call__(self, *args, **kwargs):
print("TestClass2 __call__ ")
return self
def fun(self):
print("this TestClass2 fun()")
class TestClass3:
def __call__(self, *args, **kwargs):
print("TestClass3 33333 call 3 ")
return self
def fun(self):
print("this TestClass3 fun()")
in both examples given __getattr__ is called with argument "test".
you need to do something like this:
class TestClass1:
def __getattr__(self, item):
if item == 'test2':
return TestClass2()
elif item == 'test3':
return TestClass3()
a = TestClass1()
a.test2.fun()
a.test3.fun()
EDIT: Let me explain further. Well, in python there is no difference between a function and an attribute, everything in python is an object, all objects are treated the same, be it an integer or a function.
When you do a.test it is lowered to a.__getattr__('test').
And when you do a.test(a=10) it is lowered to a.__getattr__('test')(a=10).
The returned object from a.__getattr__('test') is the same.
In the second case you are fetching the attribute test then calling it with an argument a=10.
EDIT2: What you are trying to do could be achieved this way:
class TestClass1:
test = TestClass2()
class TestClass2:
def __call__(self, a):
if a == 10:
return TestClass3()
def fun():
print("this TestClass2 fun()")
a = TestClass1()
a.test # this is TestClass2
a.test.fun # this is TestClass2.fun
a.test(a=10) # this is TestClass3
a.test(a=10).fun # this is TestClass3.fun
EDIT3: A simpler approach would be making test a function:
class TestClass1:
def test(a=None):
if a is None:
return TestClass2()
if a == 10:
return TestClass3()
a = TestClass1()
a.test().fun # TestClass2.fun
a.test(a=10).fun # TestClass3.fun

How to create a class instance without calling initializer?

Is there any way to avoid calling __init__ on a class while initializing it, such as from a class method?
I am trying to create a case and punctuation insensitive string class in Python used for efficient comparison purposes but am having trouble creating a new instance without calling __init__.
>>> class String:
def __init__(self, string):
self.__string = tuple(string.split())
self.__simple = tuple(self.__simple())
def __simple(self):
letter = lambda s: ''.join(filter(lambda s: 'a' <= s <= 'z', s))
return filter(bool, map(letter, map(str.lower, self.__string)))
def __eq__(self, other):
assert isinstance(other, String)
return self.__simple == other.__simple
def __getitem__(self, key):
assert isinstance(key, slice)
string = String()
string.__string = self.__string[key]
string.__simple = self.__simple[key]
return string
def __iter__(self):
return iter(self.__string)
>>> String('Hello, world!')[1:]
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
String('Hello, world!')[1:]
File "<pyshell#1>", line 17, in __getitem__
string = String()
TypeError: __init__() takes exactly 2 positional arguments (1 given)
>>>
What should I replace string = String(); string.__string = self.__string[key]; string.__simple = self.__simple[key] with to initialize the new object with the slices?
EDIT:
As inspired by the answer written below, the initializer has been edited to quickly check for no arguments.
def __init__(self, string=None):
if string is None:
self.__string = self.__simple = ()
else:
self.__string = tuple(string.split())
self.__simple = tuple(self.__simple())
When feasible, letting __init__ get called (and make the call innocuous by suitable arguments) is preferable. However, should that require too much of a contortion, you do have an alternative, as long as you avoid the disastrous choice of using old-style classes (there is no good reason to use old-style classes in new code, and several good reasons not to)...:
class String(object):
...
bare_s = String.__new__(String)
This idiom is generally used in classmethods which are meant to work as "alternative constructors", so you'll usually see it used in ways such as...:
#classmethod
def makeit(cls):
self = cls.__new__(cls)
# etc etc, then
return self
(this way the classmethod will properly be inherited and generate subclass instances when called on a subclass rather than on the base class).
A trick the standard pickle and copy modules use is to create an empty class, instantiate the object using that, and then assign that instance's __class__ to the "real" class. e.g.
>>> class MyClass(object):
... init = False
... def __init__(self):
... print 'init called!'
... self.init = True
... def hello(self):
... print 'hello world!'
...
>>> class Empty(object):
... pass
...
>>> a = MyClass()
init called!
>>> a.hello()
hello world!
>>> print a.init
True
>>> b = Empty()
>>> b.__class__ = MyClass
>>> b.hello()
hello world!
>>> print b.init
False
But note, this approach is very rarely necessary. Bypassing the __init__ can have some unexpected side effects, especially if you're not familiar with the original class, so make sure you know what you're doing.
Using a metaclass provides a nice solution in this example. The metaclass has limited use but works fine.
>>> class MetaInit(type):
def __call__(cls, *args, **kwargs):
if args or kwargs:
return super().__call__(*args, **kwargs)
return cls.__new__(cls)
>>> class String(metaclass=MetaInit):
def __init__(self, string):
self.__string = tuple(string.split())
self.__simple = tuple(self.__simple())
def __simple(self):
letter = lambda s: ''.join(filter(lambda s: 'a' <= s <= 'z', s))
return filter(bool, map(letter, map(str.lower, self.__string)))
def __eq__(self, other):
assert isinstance(other, String)
return self.__simple == other.__simple
def __getitem__(self, key):
assert isinstance(key, slice)
string = String()
string.__string = self.__string[key]
string.__simple = self.__simple[key]
return string
def __iter__(self):
return iter(self.__string)
>>> String('Hello, world!')[1:]
<__main__.String object at 0x02E78830>
>>> _._String__string, _._String__simple
(('world!',), ('world',))
>>>
Addendum:
After six years, my opinion favors Alex Martelli's answer more than my own approach. With meta-classes still on the mind, the following answer shows how the problem can be solved both with and without them:
#! /usr/bin/env python3
METHOD = 'metaclass'
class NoInitMeta(type):
def new(cls):
return cls.__new__(cls)
class String(metaclass=NoInitMeta if METHOD == 'metaclass' else type):
def __init__(self, value):
self.__value = tuple(value.split())
self.__alpha = tuple(filter(None, (
''.join(c for c in word.casefold() if 'a' <= c <= 'z') for word in
self.__value)))
def __str__(self):
return ' '.join(self.__value)
def __eq__(self, other):
if not isinstance(other, type(self)):
return NotImplemented
return self.__alpha == other.__alpha
if METHOD == 'metaclass':
def __getitem__(self, key):
if not isinstance(key, slice):
raise NotImplementedError
instance = type(self).new()
instance.__value = self.__value[key]
instance.__alpha = self.__alpha[key]
return instance
elif METHOD == 'classmethod':
def __getitem__(self, key):
if not isinstance(key, slice):
raise NotImplementedError
instance = self.new()
instance.__value = self.__value[key]
instance.__alpha = self.__alpha[key]
return instance
#classmethod
def new(cls):
return cls.__new__(cls)
elif METHOD == 'inline':
def __getitem__(self, key):
if not isinstance(key, slice):
raise NotImplementedError
cls = type(self)
instance = cls.__new__(cls)
instance.__value = self.__value[key]
instance.__alpha = self.__alpha[key]
return instance
else:
raise ValueError('METHOD did not have an appropriate value')
def __iter__(self):
return iter(self.__value)
def main():
x = String('Hello, world!')
y = x[1:]
print(y)
if __name__ == '__main__':
main()
Pass another argument to the constructor, like so:
def __init__(self, string, simple = None):
if simple is None:
self.__string = tuple(string.split())
self.__simple = tuple(self.__simple())
else:
self.__string = string
self.__simple = simple
You can then call it like this:
def __getitem__(self, key):
assert isinstance(key, slice)
return String(self.__string[key], self.__simple[key])
Also, I'm not sure it's allowed to name both the field and the method __simple. If only for readability, you should change that.

Categories