Python: Using eval() in class / different methods of case distinction [duplicate] - python

This question already has answers here:
Access to class attributes by using a variable in Python? [duplicate]
(2 answers)
Closed 7 years ago.
I got a class:
class thing:
def __init__(self, inp, inp2):
self.aThing = inp
self.bThing = inp2
def test(self, character):
print(self.eval(character+"Thing"))
(Important is the last line)
The test script would look like this:
x = thing(1, 2)
x.test("b")
Trying to run this it screams at me:
AttributeError: 'thing' object has no attribute 'eval'
Makes sense, so I tried this:
print(self.(eval(character+"Thing")))
Now its a Syntax error: .(
So is there a way Í could do this? And if not, is there a way to do this kind of case distinction without having to list all possible cases? (like using if-statements or the switch equivalent)
Oh, and I know that in this case I could just use a dictionary instead of a class, but that is not what I am searching for...

Your question is very broad and you're probably better off watching a talk on polymorphism and the super function(behaviour distinction without if) or python design patterns.
For the specific problem you posted you want to use getattr:
getattr(object, name[, default])
Return the value of the named
attribute of object. name must be a string. If the string is the name
of one of the object’s attributes, the result is the value of that
attribute. For example, getattr(x, 'foobar') is equivalent to
x.foobar. If the named attribute does not exist, default is returned
if provided, otherwise AttributeError is raised.
class thing:
def __init__(self, inp, inp2):
self.aThing = inp
self.bThing = inp2
def test(self, character):
print(getattr(self,character+"Thing"))
Example Demo
>>> t = thing(1, 2)
>>> t.test("a")
1

Related

How to add method to base class?

I want to add __add__ and __radd__ to the python base class set.
The code can be as simple as
def __add__(self, other) :
assert isinstance(other, set), \
"perhaps additional type checking or argument validation can go here but" + \
" strictly only defined for pure python sets"
return set( list(self) + list(other) )
def __radd__(self, other) :
assert isinstance(other, set), \
"perhaps additional type checking or argument validation can go here but" + \
" strictly only defined for pure sets"
return set( list(other) + list(self) )
What is the pythonic implementation of this and how can I extend the base class without creating my own MySet class that takes set as a parent class? Can I just use set.__add__ = some_function_I_defined?
What you should do imho is subclass the built-in set class.
In Python (contrary to e.g. Ruby or JavaScript) monkey-patching a built-in is not allowed.
So e.g. trying to add a non-existent method:
x = [1,2,3]
x.my_new_method_added_in_runtime = lambda: "whatever"
is not going to work, you'd get AttributeError: 'list' object has no attribute 'my_new_method_added_in_runtime'
You cannot also modify the existing methods of objects instantiated using those built-ins:
x = [1,2,3]
x.sort = lambda: "returning some string instead of sorting..."
will result in AttributeError: 'list' object attribute 'sort' is read-only
And
list.append = None
# OR
del list.append
will result in:
TypeError: can't set attributes of built-in/extension type 'list'
All of the above is true for set as well an so on.
You could try to look for some libraries to achieve that e.g. https://pypi.org/project/forbiddenfruit/0.1.0/, but it's strongly discouraged.
#chepner correctly answered my question without realizing it. I was trying to reimplement already existing functionality since I was not familiar with python sets.
The act of joining two sets, 'taking their union' is implemented with the python __or__ and __ior__ methods. The operation I needed specifically was | and |=.
In principle we should be able to set operations as chepner suggested with set.__add__ = set.__or__, but as chepner points out this results in an error:
TypeError: cannot set '__add__' attribute of immutable type 'set'
Thank you all.

Create a method named 'def' [duplicate]

This question already has answers here:
How do I use a keyword as a variable name?
(3 answers)
Closed 3 years ago.
Is there a way in python to override the definition of def?
Trying to create a method which will be named def, like this:
MyObject.def(arguments)
It's not possible. def is a keyword, so can't be overridden (unlike built-ins like max which can). Instead the convention is to add a trailing underscore:
class MyObject:
def def_():
pass
Although a better solution might be to expand the name: define
You can do something like this:
class A:
def x(self):
print('hi')
x.__name__ = 'def'
setattr(A, 'def', A.x)
delattr(A, 'x')
You won't be able to call the method literally:
>>> A().def()
...
A().def()
^
SyntaxError: invalid syntax
But the following will work:
>>> getattr(A(), 'def')()
'hi'
This is a terrible idea. def is a reserved keyword. While you can use the fact that class namespaces are dictionaries with string keys, please don't.

python see the full definition from the name of the function [duplicate]

This question already has answers here:
How can I get the source code of a Python function?
(13 answers)
Closed 4 years ago.
I recently asked a question with title "python find the type of a function" and got very helpful answers. Here is a related question.
Suppose I import *.py files written by me, and these imports result in f being one of the functions defined by me. Now I write to my python interpreter x = f. Later, I want to see the full definition of f, preferably with comments still in place, knowing only x. Is this possible? Does python remember which file the definition was imported from, which is, of course, not enough to give the full definition of f, unless one can find the actual relevant definition?
The built in help(object) will give you the correct documentation if you alias k to some function you commented - same for inspect.getsource(k) - they know which function is ment by your variable name alias k at this time.
See:
the help() built in
inspect.getsource(k)
(taken from here)
Example:
# reusing this code - created it for some other question today
class well_documented_example_class(object):
"""Totally well documented class"""
def parse(self, message):
"""This method does coool things with your 'message'
'message' : a string with text in it to be parsed"""
self.data = [x.strip() for x in message.split(' ')]
return self.data
# alias for `parse()`:
k = well_documented_example_class.parse
help(k)
Prints:
Help on function parse in module __main__:
parse(self, message)
This method does coool things with your 'message'
'message' : a string with text in it to be parsed
Same goes for inspect.getsource(k):
# from https://stackoverflow.com/a/52333691/7505395
import inspect
print(inspect.getsource(k))
prints:
def parse(self, message):
"""This method does coool things with your 'message'
'message' : a string with text in it to be parsed"""
self.data = [x.strip() for x in message.split(' ')]
return self.data
You should think of the way Python uses variables. You have objects (can be classes, functions, lists, scalars or whatelse) and variables that only hold references to those objects.
That explains why when multiple variables point to the same mutable object, if you change it through one of those variables, the change in visible in all other ones.
This is the same thing here. The function object manages all its attributes: its docstring, its code, and its source (if it has: C function show no source). Assigning the function to a new variable does not hide the object behind anything: you still access the original object.
Things would go differently with decorators, because the decorator creates a new object, and the original object is only available to the decorated one.

Python - Calling a class as a parameter [duplicate]

This question already has answers here:
How to access (get or set) object attribute given string corresponding to name of that attribute
(3 answers)
Closed 5 years ago.
I'm quite new in Python, but googling around did not match any answer for it .
I created a module, containing 10 GUI buttons classes. To use a button I write in code ButtonLib.TypeA(**kwargs), ButtonLib.TypeB(**kwargs) and so on.
kwargs is same for all buttons.
Buttons ( amount and type ) are selected by user (stored in button_type_vector) and not known in advance.
I wish to know if there is a way writing code more efficiently rather than:
for x in button_type_vector:
if x == 'TypeA':
ButtonLib.TypeA(**kwargs)
elif x== 'TypeB' :
ButtonLib.TypeB(**kwargs)
and so on.
by efficiently I mean something like:
for x in button_type_vector:
ButtonLib.x(**kwargs)
thnks
You can use the getattr built-in function to access attributes of an object using strings:
Return the value of the named attribute of object. name must be a string. If the string is the name of one of the object’s attributes, the result is the value of that attribute. For example, getattr(x, 'foobar') is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.
for x in button_type_vector:
getattr(ButtonLib, x)(**kwargs)
As mentioned by #MadPyhisist, modules are not some kind of magical object, and thus can be used with like any normal object could be getattr.
You could define a dictionary (preferably inside your module):
buttons = {
"TypeA": TypeA,
"TypeB": TypeB,
…
}
and then call the entry:
ButtonLib.buttons[x](**kwargs)
If your button classes have a function returning their name, you could also define the dictionary like this:
buttons = {
button_type.name: button_type
for button_type in [TypeA, TypeB, …]
}
More advanced: Python stores the name of a class in .__name__.
Even more advanced: You could get the elements of the module with getattr(ButtonLib, name). But this might impair readability.

Is there a Python equivalent to Ruby's respond_to?

Is a way to see if a class responds to a method in Python? like in ruby:
class Fun
def hello
puts 'Hello'
end
end
fun = Fun.new
puts fun.respond_to? 'hello' # true
Also is there a way to see how many arguments the method requires?
Hmmm .... I'd think that hasattr and callable would be the easiest way to accomplish the same goal:
class Fun:
def hello(self):
print 'Hello'
hasattr(Fun, 'hello') # -> True
callable(Fun.hello) # -> True
You could, of course, call callable(Fun.hello) from within an exception handling suite:
try:
callable(Fun.goodbye)
except AttributeError, e:
return False
As for introspection on the number of required arguments; I think that would be of dubious value to the language (even if it existed in Python) because that would tell you nothing about the required semantics. Given both the ease with which one can define optional/defaulted arguments and variable argument functions and methods in Python it seems that knowing the "required" number of arguments for a function would be of very little value (from a programmatic/introspective perspective).
Has method:
func = getattr(Fun, "hello", None)
if callable(func):
...
Arity:
import inspect
args, varargs, varkw, defaults = inspect.getargspec(Fun.hello)
arity = len(args)
Note that arity can be pretty much anything if you have varargs and/or varkw not None.
dir(instance) returns a list of an objects attributes.
getattr(instance,"attr") returns an object's attribute.
callable(x) returns True if x is callable.
class Fun(object):
def hello(self):
print "Hello"
f = Fun()
callable(getattr(f,'hello'))
I am no Ruby expert, so I am not sure if this answers your question. I think you want to check if an object contains a method. There are numerous ways to do so. You can try to use the hasattr() function, to see if an object hast the method:
hasattr(fun, "hello") #True
Or you can follow the python guideline don't ask to ask, just ask so, just catch the exception thrown when the object doesn't have the method:
try:
fun.hello2()
except AttributeError:
print("fun does not have the attribute hello2")

Categories

Resources